- if (flags & O_CREAT) {
- va_start(ap, flags);
- mode = va_arg(ap, mode_t) & 0666;
- value = va_arg(ap, unsigned);
- va_end(ap);
- if (value > SEM_VALUE_MAX) {
- errno = EINVAL;
- return SEM_FAILED;
- }
- sem_init(&newsem, 1, value);
- clock_gettime(CLOCK_REALTIME, &ts);
- snprintf(tmp, sizeof(tmp), "/dev/shm/%p-%p-%d-%d",
- &name, name, (int)getpid(), (int)ts.tv_nsec);
- tfd = open(tmp, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC, mode);
- if (tfd<0) return SEM_FAILED;
- dir = open("/dev/shm", O_DIRECTORY|O_RDONLY|O_CLOEXEC);
- if (dir<0 || write(tfd,&newsem,sizeof newsem)!=sizeof newsem) {
- if (dir >= 0) close(dir);
- close(tfd);
- unlink(tmp);
- return SEM_FAILED;
- }
+ /* Reserve a slot in case this semaphore is not mapped yet;
+ * this is necessary because there is no way to handle
+ * failures after creation of the file. */
+ slot = -1;
+ for (cnt=i=0; i<SEM_NSEMS_MAX; i++) {
+ cnt += semtab[i].refcnt;
+ if (!semtab[i].sem && slot < 0) slot = i;