EVL implements the classic Dijkstra semaphore construct, with an API close to the POSIX specification for the basic operations.
This call creates a semaphore, returning a file descriptor representing the new object upon success. This is the generic call form; for creating a semaphore with common pre-defined settings, see [evl_new_sem()}(#evl_new_sem).
An in-memory semaphore descriptor is constructed by
evl_create_sem(),
which contains ancillary information other calls will need. sem
is a pointer to such descriptor of type struct evl_sem
.
Some semaphore-related calls are timed like evl_timedget_sem() which receives a timeout value. You can specify the EVL clock this timeout refers to by passing its file descriptor as clockfd. Built-in EVL clocks are accepted here.
The initial value of the semaphore count.
A set of creation flags for the new element, defining its visibility:
EVL_CLONE_PUBLIC
denotes a public element which is represented
by a device file in the /dev/evl file hierarchy, which
makes it visible to other processes for sharing.
EVL_CLONE_PRIVATE
denotes an element which is private to the
calling process. No device file appears for it in the /dev/evl file hierarchy.
EVL_CLONE_NONBLOCK
sets the file descriptor of the new semaphore in
non-blocking I/O mode (O_NONBLOCK
). By default, O_NONBLOCK
is
cleared for the file descriptor.
A printf-like format string to generate the semaphore name. See this description of the naming convention.
The optional variable argument list completing the format.
evl_create_sem() returns the file descriptor of the newly created semaphore on success. Otherwise, a negated error code is returned:
-EEXIST The generated name is conflicting with an existing mutex, event, semaphore or flag group name.
-EINVAL Either clockfd does not refer to a valid EVL clock, or the generated semaphore name is badly formed, likely containing invalid character(s), such as a slash. Keep in mind that it should be usable as a basename of a device element’s file path.
-ENAMETOOLONG The overall length of the device element’s file path including the generated name exceeds PATH_MAX.
-EMFILE The per-process limit on the number of open file descriptors has been reached.
-ENFILE The system-wide limit on the total number of open files has been reached.
-ENOMEM No memory available.
-ENXIO The EVL library is not initialized for the current process. Such initialization happens implicitly when evl_attach_self() is called by any thread of your process, or by explicitly calling evl_init(). You have to bootstrap the library services in a way or another before creating an EVL semaphore.
#include <evl/sem.h>
static struct evl_sem sem;
void create_new_sem(void)
{
int fd;
fd = evl_create_sem(sem, EVL_CLOCK_MONOTONIC, 1, EVL_CLONE_PRIVATE, "name_of_semaphore");
/* skipping checks */
return fd;
}
This call is a shorthand for creating a zero-initialized private semaphore, timed on the built-in EVL monotonic clock. It is identical to calling:
evl_create_sem(sem, EVL_CLOCK_MONOTONIC, 0, EVL_CLONE_PRIVATE, fmt, ...);
Note that if the generated name starts with a
slash (‘/’) character, EVL_CLONE_PRIVATE
would be automatically turned
into EVL_CLONE_PUBLIC
internally.
The static initializer you can use with semaphores. All arguments to this macro refer to their counterpart in the call to evl_create_sem().
struct evl_sem sem = EVL_SEM_INITIALIZER("name_of_semaphore", EVL_CLOCK_MONOTONIC, 1, EVL_CLONE_PUBLIC);
You can open an existing semaphore, possibly from a different process, by calling evl_open_sem().
An in-memory semaphore descriptor is constructed by
evl_open_sem(),
which contains ancillary information other calls will need. sem is a
pointer to such descriptor of type struct evl_sem
. The information
is retrieved from the existing semaphore which was opened.
A printf-like format string to generate the name of the semaphore to open. This name must exist in the EVL device file hierarchy at /dev/evl/monitor. See this description of the naming convention.
The optional variable argument list completing the format.
evl_open_sem() returns the file descriptor referring to the opened semaphore on success, Otherwise, a negated error code is returned:
-EINVAL The name refers to an existing object, but not to a semaphore.
-EMFILE The per-process limit on the number of open file descriptors has been reached.
-ENFILE The system-wide limit on the total number of open files has been reached.
-ENOMEM No memory available.
This service decrements a semaphore by one. If the resulting semaphore value is negative, the caller is put to sleep by the core until a subsequent call to evl_put_sem() eventually releases it. Otherwise, the caller returns immediately. Waiters are queued by order of scheduling priority.
The in-memory semaphore descriptor constructed by either evl_create_sem() or evl_open_sem(), or statically built with EVL_SEM_INITIALIZER. In the latter case, an implicit call to evl_create_sem() for sem is issued before a get operation is attempted, which may trigger a transition to the in-band execution mode for the caller.
evl_get_sem() returns zero on success. Otherwise, a negated error code may be returned if:
-EINVAL sem does not represent a valid in-memory semaphore descriptor. If that pointer is out of the caller’s address space or points to read-only memory, the caller bluntly gets a memory access exception.
If sem was statically initialized with EVL_SEM_INITIALIZER, then any error returned by evl_create_sem() may be passed back to the caller in case the implicit initialization call fails.
This call is a variant of evl_get_sem() which allows specifying a timeout on the get operation, so that the caller is unblocked after a specified delay sleeping without being unblocked by a subsequent call to evl_put_sem().
The in-memory semaphore descriptor constructed by either evl_create_sem() or evl_open_sem(), or statically built with EVL_SEM_INITIALIZER. In the latter case, an implicit call to evl_create_sem() is issued for sem before a get operation is attempted, which may trigger a transition to the in-band execution mode for the caller.
A time limit to wait for the caller to be unblocked before the call returns on error. The clock mentioned in the call to evl_create_sem() will be used for tracking the elapsed time.
The possible return values include any status from evl_get_sem(), plus:
-ETIMEDOUT The timeout fired, after the amount of time specified by timeout.
This call posts a semaphore by incrementing its count by one. If a thread is sleeping on the semaphore as a result of a previous call to evl_get_sem() or evl_timedget_sem(), the thread heading the wait queue is unblocked.
The in-memory semaphore descriptor constructed by either evl_create_sem() or evl_open_sem(), or statically built with EVL_SEM_INITIALIZER. In the latter case, an implicit call to evl_create_sem() for sem is issued before the semaphore is posted, which may trigger a transition to the in-band execution mode for the caller.
evl_put_sem() returns zero upon success. Otherwise, a negated error code is returned:
-EINVAL sem does not represent a valid in-memory semaphore descriptor. If that pointer is out of the caller’s address space or points to read-only memory, the caller bluntly gets a memory access exception.
If sem was statically initialized with EVL_SEM_INITIALIZER but not passed to any semaphore-related call yet, then any error status returned by evl_create_sem() may be passed back to the caller in case the implicit initialization call fails.
This call attempts to decrement the semaphore provided the result does not lead to a negative count.
The in-memory semaphore descriptor constructed by either evl_create_sem() or evl_open_sem(), or statically built with EVL_SEM_INITIALIZER. In the latter case, an implicit call to evl_create_sem() for sem is issued before a wait is attempted, which may trigger a transition to the in-band execution mode for the caller.
evl_tryget_sem() returns zero on success. Otherwise, a negated error code may be returned if:
-EAGAIN sem count value is zero or negative at the time of the call.
-EINVAL sem does not represent a valid in-memory semaphore descriptor. If that pointer is out of the caller’s address space or points to read-only memory, the caller bluntly gets a memory access exception.
If sem was statically initialized with EVL_SEM_INITIALIZER, then any error returned by evl_create_sem() may be passed back to the caller in case the implicit initialization call fails.
This call returns the count value of the semaphore. If a negative count is returned in *r_val, its absolute value can be interpreted as the number of waiters sleeping on the semaphore’s wait queue (at the time of the call). A zero or positive value means that the semaphore is not contended.
The in-memory semaphore descriptor constructed by either evl_create_sem() or evl_open_sem(), or statically built with EVL_SEM_INITIALIZER. In the latter case, the semaphore becomes valid for a call to evl_peek_sem() only after a put or [try]get operation was issued for it.
The address of an integer which contains the semaphore value on successful return from the call.
evl_peek_sem() returns zero on success along with the current semaphore count. Otherwise, a negated error code may be returned if:
-EINVAL sem does not represent a valid in-memory semaphore descriptor. If that pointer is out of the caller’s address space or points to read-only memory, the caller bluntly gets a memory access exception.
You can use evl_close_sem() to dispose of an EVL semaphore, releasing the associated file descriptor, at which point sem will not be valid for any subsequent operation from the current process. However, this semaphore is kept alive in the EVL core until all file descriptors opened on it by call(s) to evl_open_sem() have been released, whether from the current process or any other process.
The in-memory descriptor of the semaphore to dismantle.
evl_close_sem() returns zero upon success. Otherwise, a negated error code is returned:
-EINVAL sem does not represent a valid in-memory semaphore descriptor. If that pointer is out of the caller’s address space or points to read-only memory, the caller bluntly gets a memory access exception.
Closing a statically initialized semaphore descriptor which has never been used in get or put operations always returns zero.
The evl_poll() interface can monitor the following events occurring on a semaphore file descriptor:
Last modified: Mon, 27 Apr 2020 19:01:01 CEST