197403Sobrien/* Copyright (C) 2015-2020 Free Software Foundation, Inc. 297403Sobrien Contributed by Sebastian Huber <sebastian.huber@embedded-brains.de>. 3117397Skan 497403Sobrien This file is part of the GNU Offloading and Multi Processing Library 5103447Skan (libgomp). 6103447Skan 7103447Skan Libgomp is free software; you can redistribute it and/or modify it 8103447Skan under the terms of the GNU General Public License as published by 997403Sobrien the Free Software Foundation; either version 3, or (at your option) 10103447Skan any later version. 11103447Skan 1297403Sobrien Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY 1397403Sobrien WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 1497403Sobrien FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1597403Sobrien more details. 16103447Skan 17103447Skan Under Section 7 of GPL version 3, you are granted additional 18169691Skan permissions described in the GCC Runtime Library Exception, version 19103447Skan 3.1, as published by the Free Software Foundation. 20103447Skan 2197403Sobrien You should have received a copy of the GNU General Public License and 2297403Sobrien a copy of the GCC Runtime Library Exception along with this program; 2397403Sobrien see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2497403Sobrien <http://www.gnu.org/licenses/>. */ 2597403Sobrien 2697403Sobrien/* This is the RTEMS implementation of the thread pool management 2797403Sobrien for libgomp. This type is private to the library. */ 2897403Sobrien 2997403Sobrien#ifndef GOMP_POOL_H 3097403Sobrien#define GOMP_POOL_H 1 3197403Sobrien 3297403Sobrien#include "libgomp.h" 3397403Sobrien#include <sys/lock.h> 3497403Sobrien#include <string.h> 3597403Sobrien 3697403Sobrien/* For each scheduler instance there may be a thread pool reservoir 3797403Sobrien to limit the number of thread pools used by the OpenMP master threads of this 3897403Sobrien scheduler instance. The reservoirs are configured via the 39132720Skan GOMP_RTEMS_THREAD_POOLS environment variable. */ 4097403Sobrienstruct gomp_thread_pool_reservoir { 4197403Sobrien gomp_sem_t available; 42117397Skan pthread_spinlock_t lock; 4397403Sobrien size_t index; 4497403Sobrien int priority; 4597403Sobrien struct gomp_thread_pool *pools[]; 4697403Sobrien}; 47169691Skan 48169691Skanstruct gomp_tls_rtems_data { 4997403Sobrien struct gomp_thread_pool_reservoir *thread_pool_reservoir; 5097403Sobrien}; 5197403Sobrien 5297403Sobrienextern struct gomp_thread_pool_reservoir **gomp_thread_pool_reservoirs; 5397403Sobrien 5497403Sobrienextern __thread struct gomp_tls_rtems_data gomp_tls_rtems_data; 5597403Sobrien 5697403Sobrienstatic inline struct gomp_thread_pool_reservoir * 57132720Skangomp_get_thread_pool_reservoir (void) 5897403Sobrien{ 5997403Sobrien struct gomp_thread_pool_reservoir *res = 6097403Sobrien gomp_tls_rtems_data.thread_pool_reservoir; 6197403Sobrien 6297403Sobrien if (res == NULL && gomp_thread_pool_reservoirs != NULL) 6397403Sobrien { 6497403Sobrien struct gomp_thread *thr = gomp_thread (); 6597403Sobrien thr->thread_pool = gomp_malloc_cleared (sizeof (*thr->thread_pool)); 6697403Sobrien res = gomp_thread_pool_reservoirs[_Sched_Index ()]; 6797403Sobrien gomp_tls_rtems_data.thread_pool_reservoir = res; 6897403Sobrien } 6997403Sobrien 7097403Sobrien return res; 7197403Sobrien} 7297403Sobrien 7397403Sobrienstatic inline struct gomp_thread_pool * 7497403Sobriengomp_get_own_thread_pool (struct gomp_thread *thr, unsigned nthreads) 7597403Sobrien{ 7697403Sobrien struct gomp_thread_pool *pool = thr->thread_pool; 7797403Sobrien if (__builtin_expect (pool == NULL, 0)) 78132720Skan { 7997403Sobrien pool = gomp_malloc_cleared (sizeof (*pool)); 8097403Sobrien pool->threads_busy = nthreads; 8197403Sobrien thr->thread_pool = pool; 8297403Sobrien } 8397403Sobrien return pool; 8497403Sobrien} 8597403Sobrien 8697403Sobrienstatic inline struct gomp_thread_pool * 8797403Sobriengomp_get_thread_pool (struct gomp_thread *thr, unsigned nthreads) 8897403Sobrien{ 8997403Sobrien struct gomp_thread_pool *pool; 9097403Sobrien struct gomp_thread_pool_reservoir *res; 9197403Sobrien 9297403Sobrien if (__builtin_expect (thr->thread_pool == NULL, 0)) 93132720Skan pthread_setspecific (gomp_thread_destructor, thr); 9497403Sobrien 9597403Sobrien res = gomp_get_thread_pool_reservoir (); 9697403Sobrien if (res != NULL) 9797403Sobrien { 9897403Sobrien gomp_sem_wait (&res->available); 9997403Sobrien pthread_spin_lock (&res->lock); 10097403Sobrien pool = res->pools[--res->index]; 10197403Sobrien pthread_spin_unlock (&res->lock); 10297403Sobrien pool->threads_busy = nthreads; 10397403Sobrien thr->thread_pool = pool; 10497403Sobrien } 10597403Sobrien else 10697403Sobrien pool = gomp_get_own_thread_pool (thr, nthreads); 10797403Sobrien 10897403Sobrien return pool; 109169691Skan} 110169691Skan 11197403Sobrienstatic inline void 11297403Sobriengomp_release_thread_pool (struct gomp_thread_pool *pool) 11397403Sobrien{ 114 struct gomp_thread_pool_reservoir *res = 115 gomp_tls_rtems_data.thread_pool_reservoir; 116 if (res != NULL) 117 { 118 pthread_spin_lock (&res->lock); 119 res->pools[res->index++] = pool; 120 pthread_spin_unlock (&res->lock); 121 gomp_sem_post (&res->available); 122 } 123} 124 125static inline pthread_attr_t * 126gomp_adjust_thread_attr (pthread_attr_t *attr, pthread_attr_t *mutable_attr) 127{ 128 struct gomp_thread_pool_reservoir *res = gomp_get_thread_pool_reservoir (); 129 if (res != NULL && res->priority > 0) 130 { 131 struct sched_param param; 132 int err; 133 if (attr != mutable_attr) 134 { 135 attr = mutable_attr; 136 pthread_attr_init (attr); 137 } 138 memset (¶m, 0, sizeof (param)); 139 param.sched_priority = res->priority; 140 err = pthread_attr_setschedparam (attr, ¶m); 141 if (err != 0) 142 gomp_fatal ("Thread attribute set scheduler parameters failed: %s", strerror (err)); 143 err = pthread_attr_setschedpolicy (attr, SCHED_FIFO); 144 if (err != 0) 145 gomp_fatal ("Thread attribute set scheduler policy failed: %s", strerror (err)); 146 err = pthread_attr_setinheritsched (attr, PTHREAD_EXPLICIT_SCHED); 147 if (err != 0) 148 gomp_fatal ("Thread attribute set explicit scheduler failed: %s", strerror (err)); 149 } 150 return attr; 151} 152 153#endif /* GOMP_POOL_H */ 154