// vi:ft=cpp /* * \file * \brief User-Level Semaphores. * \ingroup l4_sem_api */ /* * (c) 2008-2009 Adam Lackorzynski , * Alexander Warg * economic rights: Technische Universität Dresden (Germany) * * This file is part of TUD:OS and distributed under the terms of the * GNU General Public License 2. * Please see the COPYING-GPL-2 file for details. * * As a special exception, you may use this file as part of a free software * library without restriction. Specifically, if other files instantiate * templates or use macros or inline functions from this file, or you compile * this file and link it with other files to produce an executable, this * file does not by itself cause the resulting executable to be covered by * the GNU General Public License. This exception does not however * invalidate any other reasons why the executable file might be covered by * the GNU General Public License. */ #pragma once #include #include namespace L4 { /* * \ingroup l4_sem_api * \brief Kernel pert of the fast user semaphore. * * \#include * * \see L4::Semaphore for the full sempahore class. */ class K_semaphore : public Kobject { protected: K_semaphore(); public: /* * \brief return codes of the down operation. */ enum Returncode { OK = 0, ///< Got the semaphore. TIMEOUT = 2, ///< Timeout during blocking. INVALID = 3 ///< The semaphore does not exist, or is about to be deleted. }; long down(l4_u_semaphore_t *sem, l4_timeout_s timeout) throw() { return l4_error(l4_usem_down_to(cap(), sem, timeout)); } long down(l4_u_semaphore_t *sem) throw() { return l4_error(l4_usem_down(cap(), sem)); } long up(l4_u_semaphore_t *sem) throw() { return l4_error(l4_usem_up(cap(), sem)); } }; /* * \ingroup l4_sem_api * \brief Fast user-level semaphore. * * \#include * * This is a fast user-level semaphore implementation. It can be used * for all kinds of synchronization and is well optimized for the * non-contention case. */ class Semaphore { private: l4_u_semaphore_t _u; Cap _k; public: /* * \brief Return codes for the down operations. */ enum Returncode { OK = K_semaphore::OK, ///< Got the semaphore. TIMEOUT = K_semaphore::TIMEOUT, ///< Timeout during blocking. INVALID = K_semaphore::INVALID, ///< Semaphore does not exist, or is about to be deleted. }; /* * \brief Create a new semaphore. * \param k the capability selector for the kernel part of the semaphore. * * The kernel part must be allocated separately (see L4::Factory, * \ref l4_factory_api). You can also initialize the capability and * the counter value later by using one of the init() methods. */ Semaphore(Cap const &k = Cap::Invalid) : _k(k) { _u.counter = 0; _u.flags = 0; } /* * \brief Initialize the semaphore object. * \param cnt the initial counter value (>0 means free, <=0 means blocked). * \param k the capability for the kernel object related to that semaphore. */ void init(long cnt, Cap const &k) { _k = k; _u.counter = cnt; _u.flags = 0; } /* * \brief Initialize the semaphore object. * \param cnt the initial counter value (>0 means free, <=0 means blocked). */ void init(long cnt) { _u.counter = cnt; _u.flags = 0; } /* * \brief Do a down operation on the semaphore, with a timeout for blocking. * \param timeout the timeout to use when the operation blocks. * \return #OK on success, #TIMEOUT or #INVALID on failure. * * \note This operation will block if the counter is 0 or less. * \note To implement a try-lock semantics use a relative timeout of 0, this * shall immediately return in either case and the return value * indicates if the operation succeeded. */ long down(l4_timeout_s timeout) throw() { return _k->down(&_u, timeout); } /* * \brief Do a down operation on the semaphore. * \return #OK on success, #INVALID on failure. * * \note This operation will block if the counter is 0 or less. */ long down() throw() { return _k->down(&_u); } /* * \brief Do an up operation on the semaphore. * * \note This operation shall wakeup possibly blocked threads. */ long up() throw() { return _k->up(&_u); } /* * \brief Get the capability for the kernel part. */ Cap ksem_cap() const { return _k; } }; }