1// vi:set ft=cpp: -*- Mode: C++ -*- 2/** 3 * \file 4 * Semaphore class definition. 5 */ 6/* 7 * (c) 2015 Alexander Warg <alexander.warg@kernkonzept.com> 8 * 9 * This file is part of TUD:OS and distributed under the terms of the 10 * GNU General Public License 2. 11 * Please see the COPYING-GPL-2 file for details. 12 * 13 * As a special exception, you may use this file as part of a free software 14 * library without restriction. Specifically, if other files instantiate 15 * templates or use macros or inline functions from this file, or you compile 16 * this file and link it with other files to produce an executable, this 17 * file does not by itself cause the resulting executable to be covered by 18 * the GNU General Public License. This exception does not however 19 * invalidate any other reasons why the executable file might be covered by 20 * the GNU General Public License. 21 */ 22 23#pragma once 24 25#include <l4/sys/irq> 26#include <l4/sys/semaphore.h> 27 28namespace L4 { 29 30/** 31 * Kernel-provided semaphore object. 32 * 33 * This is the interface for kernel-provided semaphore objects. The 34 * object provides the classical functions `up()` and `down()` for 35 * counting the semaphore and blocking. The semaphore is a 36 * Triggerable with respect to the `up()` function, this means that a 37 * semaphore can be bound to an interrupt line at an ICU (L4::Icu) and 38 * incoming interrupts increment the semaphore counter. 39 * 40 * The `down()` method decrements the semaphore counter and blocks 41 * if the counter is already zero. Blocking on a semaphore may---as all 42 * blocking operations---either return successfully, or be aborted due to 43 * an expired timeout provided to the `down()` operation, or due to an 44 * L4::Thread::ex_regs() operation with the #L4_THREAD_EX_REGS_CANCEL 45 * flag set. 46 * 47 * The main reason for using a semaphore instead of an L4::Irq is to ensure 48 * that incoming trigger signals do not interfere with any open-wait 49 * operations, as used for example in a server loop. 50 */ 51struct Semaphore : Kobject_t<Semaphore, Triggerable, L4_PROTO_SEMAPHORE> 52{ 53 /** 54 * Semaphore up operation (wrapper for trigger()). 55 * 56 * \utcb{utcb} 57 * 58 * \return Send-only IPC message return tag. Use l4_ipc_error() to check for 59 * errors, do **not** use l4_error(). 60 * 61 * Increases the semaphore counter by one if it is smaller than an 62 * unspecified limit. The unspecified limit is guaranteed to be at 63 * least 2^31-1. 64 */ 65 l4_msgtag_t up(l4_utcb_t *utcb = l4_utcb()) noexcept 66 { return trigger(utcb); } 67 68 /** 69 * Semaphore down operation. 70 * 71 * \param timeout Timeout for blocking the semaphore down operation. 72 * Note: The receive timeout of this timeout-pair is 73 * significant for blocking, the send part is usually 74 * non-blocking. 75 * \utcb{utcb} 76 * 77 * \return IPC message return tag. Use l4_ipc_error() to check for 78 * a timeout or a cancel condition. 79 * 80 * This method decrements the semaphore counter by one, or blocks if the 81 * counter is already zero, until either a timeout or cancel condition hits 82 * or the counter is increased by an `up()` operation. 83 */ 84 l4_msgtag_t down(l4_timeout_t timeout = L4_IPC_NEVER, 85 l4_utcb_t *utcb = l4_utcb()) noexcept 86 { return l4_semaphore_down_u(cap(), timeout, utcb); } 87}; 88 89} 90