22 static pthread_spinlock_t lock;
23 static pthread_once_t once;
27 semtab = calloc(sizeof *semtab, SEM_NSEMS_MAX);
30 static sem_t *find_map(ino_t ino)
33 for (i=0; i<SEM_NSEMS_MAX && semtab[i].ino != ino; i++);
34 if (i==SEM_NSEMS_MAX) return 0;
35 if (semtab[i].refcnt == INT_MAX) return (sem_t *)-1;
40 sem_t *sem_open(const char *name, int flags, ...)
53 while (*name=='/') name++;
54 if (strchr(name, '/')) {
59 pthread_once(&once, init);
65 if (flags & O_CREAT) {
67 mode = va_arg(ap, mode_t) & 0666;
68 value = va_arg(ap, unsigned);
70 if (value > SEM_VALUE_MAX) {
74 sem_init(&newsem, 0, value);
75 clock_gettime(CLOCK_REALTIME, &ts);
76 snprintf(tmp, sizeof(tmp), "/dev/shm/%p-%p-%d-%d",
77 &name, name, (int)getpid(), (int)ts.tv_nsec);
78 tfd = open(tmp, O_CREAT|O_EXCL|O_RDWR, mode);
79 if (tfd<0) return SEM_FAILED;
80 dir = open("/dev/shm", O_DIRECTORY|O_RDONLY);
81 if (dir<0 || write(tfd,&newsem,sizeof newsem)!=sizeof newsem) {
82 if (dir >= 0) close(dir);
92 pthread_spin_lock(&lock);
95 if (!(flags & O_EXCL)) {
96 fd = shm_open(name, flags&~O_CREAT, mode);
97 if (fd >= 0 || errno != ENOENT) {
98 if (flags & O_CREAT) {
103 if (fd >= 0 && fstat(fd, &st) < 0) {
108 pthread_spin_unlock(&lock);
111 if ((map = find_map(st.st_ino))) {
112 pthread_spin_unlock(&lock);
114 if (map == (sem_t *)-1)
121 if (!(flags & O_CREAT)) {
122 pthread_spin_unlock(&lock);
125 if (!linkat(AT_FDCWD, tmp, dir, name, 0)) {
131 if ((flags & O_EXCL) || errno != EEXIST) {
138 if (fstat(fd, &st) < 0) {
139 pthread_spin_unlock(&lock);
143 if (semcnt == SEM_NSEMS_MAX) {
144 pthread_spin_unlock(&lock);
149 for (i=0; i<SEM_NSEMS_MAX && semtab[i].sem; i++);
150 map = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
152 if (map == MAP_FAILED) {
153 pthread_spin_unlock(&lock);
156 semtab[i].ino = st.st_ino;
158 semtab[i].refcnt = 1;
159 pthread_spin_unlock(&lock);
163 int sem_close(sem_t *sem)
166 pthread_spin_lock(&lock);
167 for (i=0; i<SEM_NSEMS_MAX && semtab[i].sem != sem; i++);
168 if (!--semtab[i].refcnt) {
172 pthread_spin_unlock(&lock);
173 return munmap(sem, sizeof *sem);