]>
sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/posix_ipc.cc
1 /* posix_ipc.cc: POSIX IPC API for Cygwin.
3 Copyright 2007 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
20 #include <sys/param.h>
28 #include <semaphore.h>
34 const char *description
;
36 { "/dev/shm", CYG_MAX_PATH
- 10, "POSIX shared memory object" },
37 { "/dev/mqueue", CYG_MAX_PATH
- 13, "POSIX message queue" },
38 { "/dev/shm", CYG_MAX_PATH
- 14, "POSIX semaphore" }
49 check_path (char *res_name
, ipc_type_t type
, const char *name
)
51 /* Note that we require the existance of the apprpriate /dev subdirectories
52 for POSIX IPC object support, similar to Linux (which supports the
53 directories, but doesn't require to mount them). We don't create
54 these directory here, that's the task of the installer. But we check
55 for existance and give ample warning. */
56 path_conv
path (ipc_names
[type
].prefix
, PC_SYM_NOFOLLOW
);
57 if (path
.error
|| !path
.exists () || !path
.isdir ())
60 "Warning: '%s' does not exists or is not a directory.\n\n"
61 "%ss require the existance of this directory.\n"
62 "Create the directory '%s' and set the permissions to 01777.\n"
63 "For instance on the command line: mkdir -m 01777 %s\n",
64 ipc_names
[type
].prefix
, ipc_names
[type
].description
,
65 ipc_names
[type
].prefix
, ipc_names
[type
].prefix
);
69 /* Name must start with a single slash. */
70 if (!name
|| name
[0] != '/' || name
[1] == '/' || !name
[1])
72 debug_printf ("Invalid %s name '%s'", ipc_names
[type
].description
, name
);
76 if (strlen (name
) > ipc_names
[type
].max_len
)
78 debug_printf ("%s name '%s' too long", ipc_names
[type
].description
, name
);
79 set_errno (ENAMETOOLONG
);
82 __small_sprintf (res_name
, "%s/%s%s", ipc_names
[type
].prefix
,
83 type
== semaphore
? "sem." : "",
89 ipc_mutex_init (HANDLE
*pmtx
, const char *name
)
91 char buf
[CYG_MAX_PATH
];
92 __small_sprintf (buf
, "%scyg_pmtx/%s",
93 wincap
.has_terminal_services () ? "Global\\" : "", name
);
94 *pmtx
= CreateMutex (&sec_all
, FALSE
, buf
);
96 debug_printf ("failed: %E\n");
97 return *pmtx
? 0 : geterrno_from_win_error ();
101 ipc_mutex_lock (HANDLE mtx
)
103 HANDLE h
[2] = { mtx
, signal_arrived
};
105 switch (WaitForMultipleObjects (2, h
, FALSE
, INFINITE
))
108 case WAIT_ABANDONED_0
:
110 case WAIT_OBJECT_0
+ 1:
116 return geterrno_from_win_error ();
120 ipc_mutex_unlock (HANDLE mtx
)
122 return ReleaseMutex (mtx
) ? 0 : geterrno_from_win_error ();
126 ipc_mutex_close (HANDLE mtx
)
128 return CloseHandle (mtx
) ? 0 : geterrno_from_win_error ();
132 ipc_cond_init (HANDLE
*pevt
, const char *name
)
134 char buf
[CYG_MAX_PATH
];
135 __small_sprintf (buf
, "%scyg_pevt/%s",
136 wincap
.has_terminal_services () ? "Global\\" : "", name
);
137 *pevt
= CreateEvent (&sec_all
, TRUE
, FALSE
, buf
);
139 debug_printf ("failed: %E\n");
140 return *pevt
? 0 : geterrno_from_win_error ();
144 ipc_cond_timedwait (HANDLE evt
, HANDLE mtx
, const struct timespec
*abstime
)
148 HANDLE h
[2] = { mtx
, evt
};
152 else if (abstime
->tv_sec
< 0
153 || abstime
->tv_nsec
< 0
154 || abstime
->tv_nsec
> 999999999)
158 gettimeofday (&tv
, NULL
);
159 /* Check for immediate timeout. */
160 if (tv
.tv_sec
> abstime
->tv_sec
161 || (tv
.tv_sec
== abstime
->tv_sec
162 && tv
.tv_usec
> abstime
->tv_nsec
/ 1000))
164 timeout
= (abstime
->tv_sec
- tv
.tv_sec
) * 1000;
165 timeout
+= (abstime
->tv_nsec
/ 1000 - tv
.tv_usec
) / 1000;
167 if (ipc_mutex_unlock (mtx
))
169 switch (WaitForMultipleObjects (2, h
, TRUE
, timeout
))
172 case WAIT_ABANDONED_0
:
176 ipc_mutex_lock (mtx
);
181 return geterrno_from_win_error ();
185 ipc_cond_signal (HANDLE evt
)
187 return SetEvent (evt
) ? 0 : geterrno_from_win_error ();
191 ipc_cond_close (HANDLE evt
)
193 return CloseHandle (evt
) ? 0 : geterrno_from_win_error ();
201 ipc_flock () { memset (&fl
, 0, sizeof fl
); }
203 int lock (int fd
, size_t size
)
206 fl
.l_whence
= SEEK_SET
;
209 return fcntl (fd
, F_SETLKW
, &fl
);
216 return fcntl (fd
, F_SETLKW
, &fl
);
220 /* POSIX shared memory object implementation. */
223 shm_open (const char *name
, int oflag
, mode_t mode
)
225 char shmname
[CYG_MAX_PATH
];
227 if (!check_path (shmname
, shmem
, name
))
230 /* Check for valid flags. */
231 if (((oflag
& O_ACCMODE
) != O_RDONLY
&& (oflag
& O_ACCMODE
) != O_RDWR
)
232 || (oflag
& ~(O_ACCMODE
| O_CREAT
| O_EXCL
| O_TRUNC
)))
234 debug_printf ("Invalid oflag 0%o", oflag
);
239 return open (shmname
, oflag
, mode
& 0777);
243 shm_unlink (const char *name
)
245 char shmname
[CYG_MAX_PATH
];
247 if (!check_path (shmname
, shmem
, name
))
250 return unlink (shmname
);
253 /* The POSIX message queue implementation is based on W. Richard STEVENS
254 implementation, just tweaked for Cygwin. The main change is
255 the usage of Windows mutexes and events instead of using the pthread
256 synchronization objects. The pathname is massaged so that the
257 files are created under /dev/mqueue. mq_timedsend and mq_timedreceive
258 are implemented additionally. */
262 struct mq_attr mqh_attr
; /* the queue's attributes */
263 long mqh_head
; /* index of first message */
264 long mqh_free
; /* index of first free message */
265 long mqh_nwait
; /* #threads blocked in mq_receive() */
266 pid_t mqh_pid
; /* nonzero PID if mqh_event set */
267 char mqh_uname
[36]; /* unique name used to identify synchronization
268 objects connected to this queue */
269 struct sigevent mqh_event
; /* for mq_notify() */
274 long msg_next
; /* index of next on linked list */
275 ssize_t msg_len
; /* actual length */
276 unsigned int msg_prio
; /* priority */
281 struct mq_hdr
*mqi_hdr
; /* start of mmap'ed region */
282 unsigned long mqi_magic
; /* magic number if open */
283 int mqi_flags
; /* flags for this process */
284 HANDLE mqi_lock
; /* mutex lock */
285 HANDLE mqi_wait
; /* and condition variable */
288 #define MQI_MAGIC 0x98765432UL
290 #define MSGSIZE(i) roundup((i), sizeof(long))
292 #define MAX_TRIES 10 /* for waiting for initialization */
294 struct mq_attr defattr
= { 0, 10, 8192, 0 }; /* Linux defaults. */
296 extern "C" _off64_t
lseek64 (int, _off64_t
, int);
297 extern "C" void *mmap64 (void *, size_t, int, int, int, _off64_t
);
300 mq_open (const char *name
, int oflag
, ...)
302 int i
, fd
, nonblock
, created
;
304 _off64_t filesize
= 0;
308 struct __stat64 statbuff
;
309 struct mq_hdr
*mqhdr
;
310 struct msg_hdr
*msghdr
;
311 struct mq_attr
*attr
;
312 struct mq_info
*mqinfo
;
314 char mqname
[CYG_MAX_PATH
];
316 if (!check_path (mqname
, mqueue
, name
))
320 if (efault
.faulted (EFAULT
))
323 oflag
&= (O_CREAT
| O_EXCL
| O_NONBLOCK
);
325 nonblock
= oflag
& O_NONBLOCK
;
326 oflag
&= ~O_NONBLOCK
;
327 mptr
= (int8_t *) MAP_FAILED
;
333 va_start (ap
, oflag
); /* init ap to final named argument */
334 mode
= va_arg (ap
, mode_t
) & ~S_IXUSR
;
335 attr
= va_arg (ap
, struct mq_attr
*);
338 /* Open and specify O_EXCL and user-execute */
339 fd
= open (mqname
, oflag
| O_EXCL
| O_RDWR
, mode
| S_IXUSR
);
342 if (errno
== EEXIST
&& (oflag
& O_EXCL
) == 0)
343 goto exists
; /* already exists, OK */
347 /* First one to create the file initializes it */
350 else if (attr
->mq_maxmsg
<= 0 || attr
->mq_msgsize
<= 0)
355 /* Calculate and set the file size */
356 msgsize
= MSGSIZE (attr
->mq_msgsize
);
357 filesize
= sizeof (struct mq_hdr
)
358 + (attr
->mq_maxmsg
* (sizeof (struct msg_hdr
) + msgsize
));
359 if (lseek64 (fd
, filesize
- 1, SEEK_SET
) == -1)
361 if (write (fd
, "", 1) == -1)
364 /* Memory map the file */
365 mptr
= (int8_t *) mmap64 (NULL
, (size_t) filesize
, PROT_READ
| PROT_WRITE
,
367 if (mptr
== (int8_t *) MAP_FAILED
)
370 /* Allocate one mq_info{} for the queue */
371 if (!(mqinfo
= (struct mq_info
*) malloc (sizeof (struct mq_info
))))
373 mqinfo
->mqi_hdr
= mqhdr
= (struct mq_hdr
*) mptr
;
374 mqinfo
->mqi_magic
= MQI_MAGIC
;
375 mqinfo
->mqi_flags
= nonblock
;
377 /* Initialize header at beginning of file */
378 /* Create free list with all messages on it */
379 mqhdr
->mqh_attr
.mq_flags
= 0;
380 mqhdr
->mqh_attr
.mq_maxmsg
= attr
->mq_maxmsg
;
381 mqhdr
->mqh_attr
.mq_msgsize
= attr
->mq_msgsize
;
382 mqhdr
->mqh_attr
.mq_curmsgs
= 0;
383 mqhdr
->mqh_nwait
= 0;
385 if (!AllocateLocallyUniqueId (&luid
))
390 __small_sprintf (mqhdr
->mqh_uname
, "cyg%016X%08x%08x",
391 hash_path_name (0,mqname
),
392 luid
.HighPart
, luid
.LowPart
);
394 index
= sizeof (struct mq_hdr
);
395 mqhdr
->mqh_free
= index
;
396 for (i
= 0; i
< attr
->mq_maxmsg
- 1; i
++)
398 msghdr
= (struct msg_hdr
*) &mptr
[index
];
399 index
+= sizeof (struct msg_hdr
) + msgsize
;
400 msghdr
->msg_next
= index
;
402 msghdr
= (struct msg_hdr
*) &mptr
[index
];
403 msghdr
->msg_next
= 0; /* end of free list */
405 /* Initialize mutex & condition variable */
406 i
= ipc_mutex_init (&mqinfo
->mqi_lock
, mqhdr
->mqh_uname
);
410 i
= ipc_cond_init (&mqinfo
->mqi_wait
, mqhdr
->mqh_uname
);
414 /* Initialization complete, turn off user-execute bit */
415 if (fchmod (fd
, mode
) == -1)
418 return ((mqd_t
) mqinfo
);
422 /* Open the file then memory map */
423 if ((fd
= open (mqname
, O_RDWR
)) < 0)
425 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
429 /* Make certain initialization is complete */
430 for (i
= 0; i
< MAX_TRIES
; i
++)
432 if (stat64 (mqname
, &statbuff
) == -1)
434 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
441 if ((statbuff
.st_mode
& S_IXUSR
) == 0)
447 set_errno (ETIMEDOUT
);
451 filesize
= statbuff
.st_size
;
452 mptr
= (int8_t *) mmap64 (NULL
, (size_t) filesize
, PROT_READ
| PROT_WRITE
,
454 if (mptr
== (int8_t *) MAP_FAILED
)
458 /* Allocate one mq_info{} for each open */
459 if (!(mqinfo
= (struct mq_info
*) malloc (sizeof (struct mq_info
))))
461 mqinfo
->mqi_hdr
= mqhdr
= (struct mq_hdr
*) mptr
;
462 mqinfo
->mqi_magic
= MQI_MAGIC
;
463 mqinfo
->mqi_flags
= nonblock
;
465 /* Initialize mutex & condition variable */
466 i
= ipc_mutex_init (&mqinfo
->mqi_lock
, mqhdr
->mqh_uname
);
470 i
= ipc_cond_init (&mqinfo
->mqi_wait
, mqhdr
->mqh_uname
);
474 return (mqd_t
) mqinfo
;
479 /* Don't let following function calls change errno */
484 if (mptr
!= (int8_t *) MAP_FAILED
)
485 munmap((void *) mptr
, (size_t) filesize
);
493 mq_getattr (mqd_t mqd
, struct mq_attr
*mqstat
)
496 struct mq_hdr
*mqhdr
;
497 struct mq_attr
*attr
;
498 struct mq_info
*mqinfo
;
501 if (efault
.faulted (EBADF
))
504 mqinfo
= (struct mq_info
*) mqd
;
505 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
510 mqhdr
= mqinfo
->mqi_hdr
;
511 attr
= &mqhdr
->mqh_attr
;
512 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
517 mqstat
->mq_flags
= mqinfo
->mqi_flags
; /* per-open */
518 mqstat
->mq_maxmsg
= attr
->mq_maxmsg
; /* remaining three per-queue */
519 mqstat
->mq_msgsize
= attr
->mq_msgsize
;
520 mqstat
->mq_curmsgs
= attr
->mq_curmsgs
;
522 ipc_mutex_unlock (mqinfo
->mqi_lock
);
527 mq_setattr (mqd_t mqd
, const struct mq_attr
*mqstat
, struct mq_attr
*omqstat
)
530 struct mq_hdr
*mqhdr
;
531 struct mq_attr
*attr
;
532 struct mq_info
*mqinfo
;
535 if (efault
.faulted (EBADF
))
538 mqinfo
= (struct mq_info
*) mqd
;
539 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
544 mqhdr
= mqinfo
->mqi_hdr
;
545 attr
= &mqhdr
->mqh_attr
;
546 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
554 omqstat
->mq_flags
= mqinfo
->mqi_flags
; /* previous attributes */
555 omqstat
->mq_maxmsg
= attr
->mq_maxmsg
;
556 omqstat
->mq_msgsize
= attr
->mq_msgsize
;
557 omqstat
->mq_curmsgs
= attr
->mq_curmsgs
; /* and current status */
560 if (mqstat
->mq_flags
& O_NONBLOCK
)
561 mqinfo
->mqi_flags
|= O_NONBLOCK
;
563 mqinfo
->mqi_flags
&= ~O_NONBLOCK
;
565 ipc_mutex_unlock (mqinfo
->mqi_lock
);
570 mq_notify (mqd_t mqd
, const struct sigevent
*notification
)
574 struct mq_hdr
*mqhdr
;
575 struct mq_info
*mqinfo
;
578 if (efault
.faulted (EBADF
))
581 mqinfo
= (struct mq_info
*) mqd
;
582 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
587 mqhdr
= mqinfo
->mqi_hdr
;
588 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
597 if (mqhdr
->mqh_pid
== pid
)
598 mqhdr
->mqh_pid
= 0; /* unregister calling process */
602 if (mqhdr
->mqh_pid
!= 0)
604 if (kill (mqhdr
->mqh_pid
, 0) != -1 || errno
!= ESRCH
)
607 ipc_mutex_unlock (mqinfo
->mqi_lock
);
611 mqhdr
->mqh_pid
= pid
;
612 mqhdr
->mqh_event
= *notification
;
614 ipc_mutex_unlock (mqinfo
->mqi_lock
);
619 _mq_send (mqd_t mqd
, const char *ptr
, size_t len
, unsigned int prio
,
620 const struct timespec
*abstime
)
623 long index
, freeindex
;
625 struct sigevent
*sigev
;
626 struct mq_hdr
*mqhdr
;
627 struct mq_attr
*attr
;
628 struct msg_hdr
*msghdr
, *nmsghdr
, *pmsghdr
;
629 struct mq_info
*mqinfo
;
632 if (efault
.faulted (EBADF
))
635 mqinfo
= (struct mq_info
*) mqd
;
636 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
641 if (prio
> MQ_PRIO_MAX
)
647 mqhdr
= mqinfo
->mqi_hdr
; /* struct pointer */
648 mptr
= (int8_t *) mqhdr
; /* byte pointer */
649 attr
= &mqhdr
->mqh_attr
;
650 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
656 if (len
> (size_t) attr
->mq_msgsize
)
658 set_errno (EMSGSIZE
);
661 if (attr
->mq_curmsgs
== 0)
663 if (mqhdr
->mqh_pid
!= 0 && mqhdr
->mqh_nwait
== 0)
665 sigev
= &mqhdr
->mqh_event
;
666 if (sigev
->sigev_notify
== SIGEV_SIGNAL
)
667 sigqueue (mqhdr
->mqh_pid
, sigev
->sigev_signo
, sigev
->sigev_value
);
668 mqhdr
->mqh_pid
= 0; /* unregister */
671 else if (attr
->mq_curmsgs
>= attr
->mq_maxmsg
)
674 if (mqinfo
->mqi_flags
& O_NONBLOCK
)
679 /* Wait for room for one message on the queue */
680 while (attr
->mq_curmsgs
>= attr
->mq_maxmsg
)
681 ipc_cond_timedwait (mqinfo
->mqi_wait
, mqinfo
->mqi_lock
, abstime
);
684 /* nmsghdr will point to new message */
685 if ((freeindex
= mqhdr
->mqh_free
) == 0)
686 api_fatal ("mq_send: curmsgs = %ld; free = 0", attr
->mq_curmsgs
);
688 nmsghdr
= (struct msg_hdr
*) &mptr
[freeindex
];
689 nmsghdr
->msg_prio
= prio
;
690 nmsghdr
->msg_len
= len
;
691 memcpy (nmsghdr
+ 1, ptr
, len
); /* copy message from caller */
692 mqhdr
->mqh_free
= nmsghdr
->msg_next
; /* new freelist head */
694 /* Find right place for message in linked list */
695 index
= mqhdr
->mqh_head
;
696 pmsghdr
= (struct msg_hdr
*) &(mqhdr
->mqh_head
);
699 msghdr
= (struct msg_hdr
*) &mptr
[index
];
700 if (prio
> msghdr
->msg_prio
)
702 nmsghdr
->msg_next
= index
;
703 pmsghdr
->msg_next
= freeindex
;
706 index
= msghdr
->msg_next
;
711 /* Queue was empty or new goes at end of list */
712 pmsghdr
->msg_next
= freeindex
;
713 nmsghdr
->msg_next
= 0;
715 /* Wake up anyone blocked in mq_receive waiting for a message */
716 if (attr
->mq_curmsgs
== 0)
717 ipc_cond_signal (mqinfo
->mqi_wait
);
720 ipc_mutex_unlock (mqinfo
->mqi_lock
);
724 ipc_mutex_unlock (mqinfo
->mqi_lock
);
729 mq_send (mqd_t mqd
, const char *ptr
, size_t len
, unsigned int prio
)
731 return _mq_send (mqd
, ptr
, len
, prio
, NULL
);
735 mq_timedsend (mqd_t mqd
, const char *ptr
, size_t len
, unsigned int prio
,
736 const struct timespec
*abstime
)
738 return _mq_send (mqd
, ptr
, len
, prio
, abstime
);
742 _mq_receive (mqd_t mqd
, char *ptr
, size_t maxlen
, unsigned int *priop
,
743 const struct timespec
*abstime
)
749 struct mq_hdr
*mqhdr
;
750 struct mq_attr
*attr
;
751 struct msg_hdr
*msghdr
;
752 struct mq_info
*mqinfo
;
755 if (efault
.faulted (EBADF
))
758 mqinfo
= (struct mq_info
*) mqd
;
759 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
764 mqhdr
= mqinfo
->mqi_hdr
; /* struct pointer */
765 mptr
= (int8_t *) mqhdr
; /* byte pointer */
766 attr
= &mqhdr
->mqh_attr
;
767 if ((n
= ipc_mutex_lock (mqinfo
->mqi_lock
)) != 0)
773 if (maxlen
< (size_t) attr
->mq_msgsize
)
775 set_errno (EMSGSIZE
);
778 if (attr
->mq_curmsgs
== 0) /* queue is empty */
780 if (mqinfo
->mqi_flags
& O_NONBLOCK
)
785 /* Wait for a message to be placed onto queue */
787 while (attr
->mq_curmsgs
== 0)
788 ipc_cond_timedwait (mqinfo
->mqi_wait
, mqinfo
->mqi_lock
, abstime
);
792 if ((index
= mqhdr
->mqh_head
) == 0)
793 api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr
->mq_curmsgs
);
795 msghdr
= (struct msg_hdr
*) &mptr
[index
];
796 mqhdr
->mqh_head
= msghdr
->msg_next
; /* new head of list */
797 len
= msghdr
->msg_len
;
798 memcpy(ptr
, msghdr
+ 1, len
); /* copy the message itself */
800 *priop
= msghdr
->msg_prio
;
802 /* Just-read message goes to front of free list */
803 msghdr
->msg_next
= mqhdr
->mqh_free
;
804 mqhdr
->mqh_free
= index
;
806 /* Wake up anyone blocked in mq_send waiting for room */
807 if (attr
->mq_curmsgs
== attr
->mq_maxmsg
)
808 ipc_cond_signal (mqinfo
->mqi_wait
);
811 ipc_mutex_unlock (mqinfo
->mqi_lock
);
815 ipc_mutex_unlock (mqinfo
->mqi_lock
);
820 mq_receive (mqd_t mqd
, char *ptr
, size_t maxlen
, unsigned int *priop
)
822 return _mq_receive (mqd
, ptr
, maxlen
, priop
, NULL
);
826 mq_timedreceive (mqd_t mqd
, char *ptr
, size_t maxlen
, unsigned int *priop
,
827 const struct timespec
*abstime
)
829 return _mq_receive (mqd
, ptr
, maxlen
, priop
, abstime
);
835 long msgsize
, filesize
;
836 struct mq_hdr
*mqhdr
;
837 struct mq_attr
*attr
;
838 struct mq_info
*mqinfo
;
841 if (efault
.faulted (EBADF
))
844 mqinfo
= (struct mq_info
*) mqd
;
845 if (mqinfo
->mqi_magic
!= MQI_MAGIC
)
850 mqhdr
= mqinfo
->mqi_hdr
;
851 attr
= &mqhdr
->mqh_attr
;
853 if (mq_notify (mqd
, NULL
)) /* unregister calling process */
856 msgsize
= MSGSIZE (attr
->mq_msgsize
);
857 filesize
= sizeof (struct mq_hdr
)
858 + (attr
->mq_maxmsg
* (sizeof (struct msg_hdr
) + msgsize
));
859 if (munmap (mqinfo
->mqi_hdr
, filesize
) == -1)
862 mqinfo
->mqi_magic
= 0; /* just in case */
863 ipc_cond_close (mqinfo
->mqi_wait
);
864 ipc_mutex_close (mqinfo
->mqi_lock
);
870 mq_unlink (const char *name
)
872 char mqname
[CYG_MAX_PATH
];
874 if (!check_path (mqname
, mqueue
, name
))
876 if (unlink (mqname
) == -1)
881 /* POSIX named semaphore implementation. Loosely based on Richard W. STEPHENS
882 implementation as far as sem_open is concerned, but under the hood using
883 the already existing semaphore class in thread.cc. Using a file backed
884 solution allows to implement kernel persistent named semaphores. */
889 unsigned long long hash
;
894 sem_open (const char *name
, int oflag
, ...)
899 unsigned int value
= 0;
900 struct __stat64 statbuff
;
901 sem_t
*sem
= SEM_FAILED
;
903 char semname
[CYG_MAX_PATH
];
904 bool wasopen
= false;
907 if (!check_path (semname
, semaphore
, name
))
911 if (efault
.faulted (EFAULT
))
915 oflag
&= (O_CREAT
| O_EXCL
);
920 va_start (ap
, oflag
); /* init ap to final named argument */
921 mode
= va_arg (ap
, mode_t
) & ~S_IXUSR
;
922 value
= va_arg (ap
, unsigned int);
925 /* Open and specify O_EXCL and user-execute */
926 fd
= open (semname
, oflag
| O_EXCL
| O_RDWR
, mode
| S_IXUSR
);
929 if (errno
== EEXIST
&& (oflag
& O_EXCL
) == 0)
930 goto exists
; /* already exists, OK */
934 /* First one to create the file initializes it. */
935 if (!AllocateLocallyUniqueId (&sf
.luid
))
941 sf
.hash
= hash_path_name (0, semname
);
942 if (write (fd
, &sf
, sizeof sf
) != sizeof sf
)
944 sem
= semaphore::open (sf
.hash
, sf
.luid
, fd
, oflag
, mode
, value
, wasopen
);
945 if (sem
== SEM_FAILED
)
947 /* Initialization complete, turn off user-execute bit */
948 if (fchmod (fd
, mode
) == -1)
950 /* Don't close (fd); */
955 /* Open the file and fetch the semaphore name. */
956 if ((fd
= open (semname
, O_RDWR
)) < 0)
958 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
962 /* Make certain initialization is complete */
963 for (i
= 0; i
< MAX_TRIES
; i
++)
965 if (stat64 (semname
, &statbuff
) == -1)
967 if (errno
== ENOENT
&& (oflag
& O_CREAT
))
974 if ((statbuff
.st_mode
& S_IXUSR
) == 0)
980 set_errno (ETIMEDOUT
);
983 if (file
.lock (fd
, sizeof sf
))
985 if (read (fd
, &sf
, sizeof sf
) != sizeof sf
)
987 sem
= semaphore::open (sf
.hash
, sf
.luid
, fd
, oflag
, mode
, sf
.value
, wasopen
);
989 if (sem
== SEM_FAILED
)
991 /* If wasopen is set, the semaphore was already opened and we already have
992 an open file descriptor pointing to the file. This means, we have to
993 close the file descriptor created in this call. It won't be stored
1000 /* Don't let following function calls change errno */
1006 if (sem
!= SEM_FAILED
)
1007 semaphore::close (sem
);
1013 _sem_close (sem_t
*sem
, bool do_close
)
1019 if (semaphore::getinternal (sem
, &fd
, &sf
.hash
, &sf
.luid
, &sf
.value
) == -1)
1021 if (!file
.lock (fd
, sizeof sf
)
1022 && lseek64 (fd
, 0LL, SEEK_SET
) != (_off64_t
) -1
1023 && write (fd
, &sf
, sizeof sf
) == sizeof sf
)
1024 ret
= do_close
? semaphore::close (sem
) : 0;
1026 /* Don't let following function calls change errno */
1035 sem_close (sem_t
*sem
)
1037 return _sem_close (sem
, true);
1041 sem_unlink (const char *name
)
1043 char semname
[CYG_MAX_PATH
];
1045 if (!check_path (semname
, semaphore
, name
))
1047 if (unlink (semname
) == -1)
This page took 0.082832 seconds and 6 git commands to generate.