forked from cloudius-systems/osv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsem.cc
72 lines (61 loc) · 1.64 KB
/
sem.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
* Copyright (C) 2013 Cloudius Systems, Ltd.
*
* This work is open source software, licensed under the terms of the
* BSD license as described in the LICENSE file in the top-level directory.
*/
#include <semaphore.h>
#include <osv/semaphore.hh>
#include <osv/sched.hh>
#include <memory>
#include "libc.hh"
// FIXME: smp safety
struct indirect_semaphore : std::unique_ptr<semaphore> {
explicit indirect_semaphore(unsigned units)
: std::unique_ptr<semaphore>(new semaphore(units)) {}
};
indirect_semaphore& from_libc(sem_t* p)
{
return *reinterpret_cast<indirect_semaphore*>(p);
}
int sem_init(sem_t* s, int pshared, unsigned val)
{
static_assert(sizeof(indirect_semaphore) <= sizeof(*s), "sem_t overflow");
new (s) indirect_semaphore(val);
return 0;
}
int sem_destroy(sem_t *s)
{
from_libc(s).~indirect_semaphore();
return 0;
}
int sem_post(sem_t* s)
{
from_libc(s)->post();
return 0;
}
int sem_wait(sem_t* s)
{
from_libc(s)->wait();
return 0;
}
int sem_timedwait(sem_t* s, const struct timespec *abs_timeout)
{
if ((abs_timeout->tv_sec < 0) || (abs_timeout->tv_nsec < 0) || (abs_timeout->tv_nsec > 1000000000LL)) {
return libc_error(EINVAL);
}
sched::timer tmr(*sched::thread::current());
osv::clock::wall::time_point time(std::chrono::seconds(abs_timeout->tv_sec) +
std::chrono::nanoseconds(abs_timeout->tv_nsec));
tmr.set(time);
if (!from_libc(s)->wait(1, &tmr)) {
return libc_error(ETIMEDOUT);
}
return 0;
}
int sem_trywait(sem_t* s)
{
if (!from_libc(s)->trywait())
return libc_error(EAGAIN);
return 0;
}