/* * remote_barrier.h - Access a POSIX barrier. * * Author Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _REMOTE_BARRIER_H_ #define _REMOTE_BARRIER_H_ #include #include #include #include /*************************************************************************************** * This file defines a POSIX compliant barrier. * * It is used by multi-threaded applications to synchronise threads running in * different clusters, as all access functions uses hal_remote_lw() / hal_remote_sw() * portable remote access primitives. * * A barrier is declared by a given user process as a "pthread_barrier_t" global variable. * This user type is implemented as an unsigned long, but the value is not used by the * kernel. ALMOS-MKH uses only the barrier virtual address as an identifier. * For each user barrier, ALMOS-MKH creates a kernel "remote_barrier_t" structure, * dynamically allocated in the reference cluster by the remote_barrier_create() function, * and destroyed by the remote_barrier_destroy() function, using RPC if the calling thread * is not running in the reference cluster. * * The blocking "remote_barrier_wait()" function implements a descheduling policy when * the calling thread is not the last expected thread: the calling thread is registered * in a waiting queue, rooted in the barrier structure, and the the calling thread * is blocked on the THREAD_BLOCKED_USERSYNC condition. The last arrived thread * unblocks all registtered waiting threads. * * Implementation note: * This barrier is also used by the kernel in the parallel kernel_init phase, as the * remote_barrier() function does not require barrier initialisation, when the barrier * is statically allocated by the compiler in the kdata segment. * **************************************************************************************/ /***************************************************************************************** * This structure defines the barrier descriptor. * - It contains an xlist of all barriers dynamically created by a given process, * rooted in the reference process descriptor. * - It contains the root of another xlist to register all arrived threads. ****************************************************************************************/ typedef struct remote_barrier_s { remote_spinlock_t lock; /*! lock protecting list of arrived threads */ intptr_t ident; /*! virtual address in user space == identifier */ uint32_t current; /*! number of arrived threads */ uint32_t sense; /*! barrier state (toggle) */ uint32_t nb_threads; /*! number of expected threads */ xlist_entry_t list; /*! member of list of barriers in same process */ xlist_entry_t root; /*! root of list of arrived threads */ } remote_barrier_t; /***************************************************************************************** * This function is directly used by the kernel in the kernel_init phase, * because it does not require barrier state initialisation. * It returns only when the expected threads reach the barrier. ***************************************************************************************** * @ barrier_xp : extended pointer on barrier descriptor. * @ count : number of expected threads. ****************************************************************************************/ inline void remote_barrier( xptr_t barrier_xp, uint32_t count ); /***************************************************************************************** * This function returns an extended pointer on the remote barrier identified * by its virtual address in a given user process. It makes an associative search, * scanning the list of barriers rooted in the reference process descriptor. ***************************************************************************************** * @ ident : barrier virtual address, used as identifier. * @ returns extended pointer on barrier if success / returns XPTR_NULL if not found. ****************************************************************************************/ xptr_t remote_barrier_from_ident( intptr_t ident ); /***************************************************************************************** * This function implement the pthread_barrier_init() syscall. * It allocates memory for the barrier descriptor in the reference cluster for * the calling process, it initializes the barrier state, and register it in the * list of barriers owned by the reference process. ***************************************************************************************** * @ count : number of expected threads. * @ ident : barrier identifier (virtual address in user space). * @ return 0 if success / return ENOMEM if failure. ****************************************************************************************/ error_t remote_barrier_create( intptr_t ident, uint32_t count ); /***************************************************************************************** * This function implement the pthread_barrier_destroy() syscall. * It releases thr memory allocated for the barrier descriptor, and remove the barrier * from the list of barriers owned by the reference process. ***************************************************************************************** * @ barrier_xp : extended pointer on barrier descriptor. ****************************************************************************************/ void remote_barrier_destroy( xptr_t barrier_xp ); /***************************************************************************************** * This function implement the pthread_barrier_wait() syscall. * It returns only when the number of expected threads (registered in the barrier * dexcriptor) reach the barrier. ***************************************************************************************** * @ barrier_xp : extended pointer on barrier descriptor. ****************************************************************************************/ void remote_barrier_wait( xptr_t barrier_xp ); #endif /* _REMOTE_BARRIER_H_ */