diff options
| author | William Bryan <wilbryan@us.ibm.com> | 2016-06-20 12:22:09 -0500 |
|---|---|---|
| committer | William A. Bryan <wilbryan@us.ibm.com> | 2016-06-20 16:00:22 -0400 |
| commit | be72a02c54979ecee2a57649c6f9dd49ca5f2525 (patch) | |
| tree | 8f37b9a6d44375ea0907155c1f05a16d80ab18e1 /src/lib/common | |
| parent | a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969 (diff) | |
| download | talos-occ-be72a02c54979ecee2a57649c6f9dd49ca5f2525.tar.gz talos-occ-be72a02c54979ecee2a57649c6f9dd49ca5f2525.zip | |
Remove non product code files
Change-Id: Ib42630c94b0e0fbed2bd8c5939fde026af87a212
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/26055
Tested-by: FSP CI Jenkins
Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Diffstat (limited to 'src/lib/common')
| -rw-r--r-- | src/lib/common/libcommonfiles.mk | 4 | ||||
| -rw-r--r-- | src/lib/common/rand.h | 124 | ||||
| -rw-r--r-- | src/lib/common/rand32.c | 384 | ||||
| -rw-r--r-- | src/lib/common/sync.c | 294 | ||||
| -rw-r--r-- | src/lib/common/sync.h | 167 |
5 files changed, 1 insertions, 972 deletions
diff --git a/src/lib/common/libcommonfiles.mk b/src/lib/common/libcommonfiles.mk index 9fe7592..4a05fac 100644 --- a/src/lib/common/libcommonfiles.mk +++ b/src/lib/common/libcommonfiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # @@ -44,9 +44,7 @@ C-SOURCES = \ memcpy.c \ memset.c \ - rand32.c \ string.c \ - sync.c S-SOURCES = diff --git a/src/lib/common/rand.h b/src/lib/common/rand.h deleted file mode 100644 index 369b8fd..0000000 --- a/src/lib/common/rand.h +++ /dev/null @@ -1,124 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/lib/common/rand.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#ifndef __RAND_H__ -#define __RAND_H__ - -// $Id$ - -/// \file rand.h -/// \brief Random number generation - -#include <stdint.h> - -// Error/Panic codes - -#define RAND64_UNIMPLEMENTED 0x00726301 - - -/// RAND32_ALL is used as the \a limit argument to rand32() and _rand32() to -/// request the return of a full 32-bit random unsigned integer. - -#define RAND32_ALL 0 - -extern uint32_t _seed32; - -uint32_t -_rand32(uint32_t *seed, uint32_t limit); - -uint32_t -rand32(uint32_t limit); - -void -srand32(uint32_t seed); - - -/// RAND64_ALL is used as the \a limit argument to rand64() and _rand64() to -/// request the return of a full 64-bit random unsigned integer. - -#define RAND64_ALL 0 - -extern uint64_t _seed64; - -//void -//davidmult64to128(uint64_t u, uint64_t v, uint64_t &h, uint64_t &l); - -uint64_t -_rand64(uint64_t *seed, uint64_t limit); - -uint64_t -rand64(uint64_t limit); - -void -srand64(uint64_t seed); - - -/// A random weighting map for integer selections -/// -/// See rand_map_int() for details. - -typedef struct { - - /// The relative weight of this selection - /// - /// The final weight of the map array \e must be 0 to terminate the map. - unsigned weight; - - /// The selection - int selection; - -} RandMapInt; - - -/// A random weighting map for pointer selections -/// -/// See rand_map_ptr() for details. - -typedef struct { - - /// The relative weight of this selection - /// - /// The final weight of the map array \e must be 0 to terminate the map. - unsigned weight; - - /// The selection - void *selection; - -} RandMapPtr; - - -int -_rand_map_int(uint32_t *seed, RandMapInt *map, int *index); - -int -rand_map_int(RandMapInt *map); - -void * -_rand_map_ptr(uint32_t *seed, RandMapPtr *map, int *index); - -void * -rand_map_ptr(RandMapPtr *map); - - -#endif /* __RAND_H__ */ diff --git a/src/lib/common/rand32.c b/src/lib/common/rand32.c deleted file mode 100644 index c75fc76..0000000 --- a/src/lib/common/rand32.c +++ /dev/null @@ -1,384 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/lib/common/rand32.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -// $Id$ - -/// \file rand32.c -/// \brief 32-bit unsigned pseudo-random number generation - -#include "rand.h" - -/// The default seed for rand32() - -uint32_t _seed32 = 405405405; - - -/// Generate a random 32-bit unsigned integer from an explicit seed -/// -/// \param seed A pointer to the random seed (updated by this routine). -/// -/// \param limit The (exclusive) upper bound of the range of generated random -/// integers. The (inclusive) lower bound is always 0. -/// -/// \retval A pseudo-random unsigned 32-bit integer uniformly selected from -/// the range 0 to \a limit - 1 (inclusive). However if the \a limit parameter -/// is \c RAND32_ALL (0), then the return value is a full 32-bit random bit -/// vector. -/// -/// This is a 32-bit linear congruential generator, taken from the 'ranqd1' -/// generator from "Numerical Recipes in C". The authors' only praise for -/// this generator is that it is "\e very fast"; the quality of random numbers -/// is deemed "entirely adequate for many uses". -/// -/// The initial 32 pseudo-random result is treated as a 32-bit binary fraction -/// that is multipled by the limit to yield the final random 32-bit -/// integer. If the limit is 0, then the full 32-bit result is returned. As -/// with all LCG, do not count on the low-order bits to be particularly -/// random. - -uint32_t -_rand32(uint32_t *seed, uint32_t limit) -{ - uint64_t x; - - *seed = (*seed * 1664525) + 1013904223; - if (limit == RAND32_ALL) { - return *seed; - } else { - x = (uint64_t)(*seed) * limit; - return x >> 32; - } -} - - -/// Generate a random 32-bit unsigned integer from a system-wide seed -/// -/// \param limit The (exclusive) upper bound of the range of generated random -/// integers. The (inclusive) lower bound is always 0. -/// -/// \retval A pseudo-random unsigned 32-bit integer uniformly selected from -/// the range 0 to \a limit - 1 (inclusive). However if the \a limit parameter -/// is \c RAND32_ALL (0), then the return value is a full 32-bit random bit -/// vector. -/// -/// rand32() is not thread safe. There is a small possibility that multiple -/// threads may observe the same random numbers, and it is also possible that -/// the random sequence may appear to repeat due to thread interactions. If -/// these are concerns then the application should either call rand32() from -/// within a critical section, or provide a unique seed to each thread or -/// process and use the underlying _rand32() API explicitly. - -uint32_t -rand32(uint32_t limit) -{ - return _rand32(&_seed32, limit); -} - - -/// Set the global random seed for rand32() - -void -srand32(uint32_t seed) -{ - _seed32 = seed; -} - - -/// Select an integer from a weighted distribution using a specific seed -/// -/// \param seed A 32-bit unsigned random seed (accumulator) -/// -/// \param map An array of RandMapInt structures, the final element of which -/// must have the \a weight field = 0. This array will typically be allocated -/// statically. -/// -/// \param index An optional pointer to an integer which will recieve the -/// index of the item selected. NULL \a index are ignored. This is provided -/// for appplications that require statistics on selections. -/// -/// \retval One of the \a selection from the array with a non-0 \a weight. If -/// the weight array is NULL (= {{0, \<dont care\>}}), then by convention the -/// return value is 0, and the return index is -1. -/// -/// This routine selects items from the \a map randomly, given the weighting -/// implied by (map[i].weight / SUM(i = 0,...,N, map[i].weight)). For -/// example, the following two maps are equivalent in that they select 'a' and -/// 'c' with 25% probability, and 'b' with 50% probability: -/// -/// RandMapInt map0[] = {{1, 'a'}, {2, 'b'}, {1, 'c'}, {0, 0}}; -/// -/// RandMapInt map1[] = {{25, 'a'}, {50, 'b'}, {25, 'c'}, {0, 0}}; -/// -/// Note that several errors including negative weights, or the overflow of -/// the sum of weights as an \a unsigned number are neither detected nor -/// reported. -/// -/// \todo We could probably merge the code for the integer and pointer versions -/// somewhat. This is a great example of where C++ would be nice, as we could -/// easily cache the sum of weights when the map was constructed. - -int -_rand_map_int(uint32_t *seed, RandMapInt *map, int *index) -{ - unsigned weight, sum; - RandMapInt *p; - uint32_t rand; - int i = -1; - int selection = 0; - - sum = 0; - p = map; - while (p->weight != 0) { - sum += p->weight; - p++; - } - - if (sum != 0) { - - rand = _rand32(seed, sum); - - weight = 0; - p = map; - i = 0; - while (p->weight != 0) { - weight += p->weight; - if (rand < weight) { - selection = p->selection; - break; - } - p++; - i++; - } - } - - if (index != 0) { - *index = i; - } - - return selection; -} - - -/// Select an integer from a weighted distribution using the system-side seed -/// \a _seed32 -/// -/// See _rand_map_int() for documentation - -int -rand_map_int(RandMapInt *map) -{ - return _rand_map_int(&_seed32, map, 0); -} - - -/// Select a pointer from a weighted distribution using a specific seed -/// -/// \param seed A 32-bit unsigned random seed (accumulator) -/// -/// \param map An array of RandMapPtr structures, the final element of which -/// must have the \a weight field = 0. This array will typically be allocated -/// statically. -/// -/// \param index An optional pointer to an integer which will recieve the -/// index of the item selected. NULL \a index are ignored. This is provided -/// for appplications that require statistics on selections. -/// -/// \retval One of the \a selection from the array with a non-0 \a weight. If -/// the weight array is NULL (= {{0, \<dont care\>}}), then by convention the -/// return value is 0, and the return index is -1; -/// -/// This routine selects items from the \a map randomly, given the weighting -/// implied by (map[i].weight / SUM(i = 0,...,N, map[i].weight)). For -/// example, the following two maps are equivalent in that they select &a and -/// &c with 25% probability, and &b with 50% probability: -/// -/// RandMapPtr map0[] = {{1, &a}, {2, &b}, {1, &c}, {0, 0}}; -/// -/// RandMapPtr map1[] = {{25, &a}, {50, &b}, {25, &c}, {0, 0}}; -/// -/// Note that several errors including negative weights, or the overflow of -/// the sum of weights as an \a unsigned number are neither detected nor -/// reported. - - -void * -_rand_map_ptr(uint32_t *seed, RandMapPtr *map, int *index) -{ - unsigned weight, sum; - RandMapPtr *p; - uint32_t rand; - int i = -1; - void *selection = 0; - - sum = 0; - p = map; - while (p->weight != 0) { - sum += p->weight; - p++; - } - - if (sum != 0) { - - rand = _rand32(seed, sum); - - weight = 0; - p = map; - i = 0; - while (p->weight != 0) { - weight += p->weight; - if (rand < weight) { - selection = p->selection; - break; - } - p++; - i++; - } - } - - if (index != 0) { - *index = i; - } - - return selection; -} - - -/// Select a pointer from a weighted distribution using the system-side seed -/// \a _seed32 -/// -/// See _rand_map_ptr() for documentation - -void * -rand_map_ptr(RandMapPtr *map) -{ - return _rand_map_ptr(&_seed32, map, 0); -} - - -//////////////////////////////////////////////////////////////////////////// - -#ifdef __TEST_RAND_C__ - -#include <stdio.h> -#include <stdlib.h> - -#ifdef RANDOM_MAP - -// Weighted distribution testing - -int a, b, c; -int aa, bb, cc; - -int x[3]; - -RandMapPtr map0[] = {{1, &a}, {2, &b}, {1, &c}, {0, 0}}; -RandMapPtr map1[] = {{25, &aa}, {50, &bb}, {25, &cc}, {0, 0}}; - -RandMapInt map2[] = {{25, 0}, {50, 1}, {25, 2}, {0, 0}}; - -int -main() -{ - int i, j; - int *p; - - for (i = 0; i < 1000000; i++) { - p = (int *)(rand_map_ptr(map0)); - *p = *p + 1; - p = (int *)(rand_map_ptr(map1)); - *p = *p + 1; - j = rand_map_int(map2); - x[j]++; - } - - printf("%d %d %d\n", a, b, c); - printf("%d %d %d\n", aa, bb, cc); - printf("%d %d %d\n", x[0], x[1], x[2]); - - return 0; -} - -#endif /* RANDOM_MAP */ - - -#ifdef BASIC_TEST - -// Simple self-checking uniform distrubution tests for rand32. - -void -test(int *a, int size, int count, double max_error) -{ - int i; - double error; - - for (i = 0; i < size; i++) { - a[i] = 0; - } - - for (i = 0; i < size * count; i++) { - a[rand32(size)]++; - } - - for (i = 0; i < size; i++) { - error = (a[i] / (double)count) - 1.0; - printf("a[%4d] : %10d %.5f\n", i, a[i], error); - if (abs(error) > max_error) { - printf("Too much error\n"); - exit(1); - } - } -} - -#define MAX_SIZE 128 - -int -main() -{ - int a[MAX_SIZE]; - int count = 1000000; - double max_error = .005; - int i; - - for (i = 2; i <= MAX_SIZE; i *= 2) { - printf("\nTest %d\n\n", i); - test(a, i, count, max_error); - } - - srand32(0); - for (i = 2; i <= MAX_SIZE; i *= 2) { - printf("\nTest %d\n\n", i); - test(a, i, count, max_error); - } - - srand32(0xdeadbeef); - for (i = 2; i <= MAX_SIZE; i *= 2) { - printf("\nTest %d\n\n", i); - test(a, i, count, max_error); - } -} - -#endif /* BASIC_TEST */ - -#endif /* __TEST_RAND_C__ */ - diff --git a/src/lib/common/sync.c b/src/lib/common/sync.c deleted file mode 100644 index a489be8..0000000 --- a/src/lib/common/sync.c +++ /dev/null @@ -1,294 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/lib/common/sync.c $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -// $Id$ - -/// \file sync.c -/// \brief A library of higher-level synchronization primitives based on -/// low-level kernel services. -/// -/// The APIs provided here are currently based on kernel services, but the -/// specifications should allow applications to be ported to other -/// environments if required. Note that like kernel services, data -/// structures manipulated by this code are protected in KERN_NONCRITICAL -/// critical sections. - -#include "kernel.h" -#include "sync.h" - -/// Create a Barrier -/// -/// \param barrier A pointer to an uninitialized or currently unused Barrier -/// -/// \param count The number of threads required to pend at the barrier before -/// all threads are released again for execution. Note that \a count values -/// of 0 and 1 are treated as equivalent - threads will not pend at all in -/// these cases. Also note that if a watchdog thread is being used, the -/// watchdog thread should not be included in the count. -/// -/// \retval 0 Success -/// -/// \retval -SYNC_INVALID_OBJECT The \a barrier is NULL (0) - -int -barrier_create(Barrier *barrier, KERN_SEMAPHORE_COUNT count) -{ - if (KERN_ERROR_CHECK_API) { - KERN_ERROR_IF(barrier == 0, SYNC_INVALID_OBJECT); - } - - barrier->entry_sem = &(barrier->sem[0]); - barrier->exit_sem = &(barrier->sem[1]); - - KERN_SEMAPHORE_CREATE((KERN_SEMAPHORE *)(barrier->entry_sem), 0, 0); - KERN_SEMAPHORE_CREATE((KERN_SEMAPHORE *)(barrier->exit_sem), 0, 0); - - barrier->entry_count = 0; - barrier->exit_count = 0; - barrier->target_count = count; - - barrier->watchdog_pending = 0; - barrier->watchdog_entries = 0; - - barrier->callback = 0; - barrier->arg = 0; - barrier->run_callback = 0; - - return 0; -} - - -/// Install a barrier callback -/// -/// \param barrier A pointer to an initialized Barrier object -/// -/// \param callback A function taking a single (void *) argument, to be -/// executed in the context of the first thread to exit the barrier when the -/// barrier condition is met. -/// -/// \param arg The argument of the \a callback. -/// -/// The Barrier object supports an optional callback function. The callback -/// (with the customary single (void *) parameter) is made when the barrier -/// condition is met, in the thread context of the first (highest priority) -/// thread to exit the barrier. The callback is made inside the barrier_pend() -/// call, but outside of a critical section. The specification of the callback -/// is not part of the barrier_create() call, but is provided later by this -/// API. Setting a NULL (0) callback disables the callback mechanism. -/// -/// \retval 0 Success -/// -/// \retval -SYNC_INVALID_OBJECT The \a barrier is NULL (0) - -int -barrier_callback_set(Barrier *barrier, - BarrierCallback callback, - void *arg) -{ - KERN_MACHINE_CONTEXT ctx; - - if (KERN_ERROR_CHECK_API) { - KERN_ERROR_IF(barrier == 0, SYNC_INVALID_OBJECT); - } - - KERN_CRITICAL_SECTION_ENTER(KERN_NONCRITICAL, &ctx); - - barrier->callback = callback; - barrier->arg = arg; - - KERN_CRITICAL_SECTION_EXIT(&ctx); - - return 0; -} - - -static int -_barrier_pend(Barrier *barrier, int watchdog) -{ - KERN_MACHINE_CONTEXT ctx; - int rc = 0; - KERN_SEMAPHORE *temp_sem; - BarrierCallback callback = 0; /* Make GCC Happy */ - void *arg = 0; /* Make GCC Happy */ - int run_callback; - - if (KERN_ERROR_CHECK_API) { - KERN_ERROR_IF(barrier == 0, SYNC_INVALID_OBJECT); - } - - KERN_CRITICAL_SECTION_ENTER(KERN_NONCRITICAL, &ctx); - - // A normal thread will pend at the entry unless 1) the thread satisfies - // the barrier condition, or 2) a watchdog thread is pending here. A - // watchdog thread only pends if no other threads are pending. - - if (watchdog) { - barrier->watchdog_entries++; - } - - barrier->entry_count++; - if (!barrier->watchdog_pending && - ((watchdog && (barrier->entry_count == 1)) || - (!watchdog && (barrier->entry_count < barrier->target_count)))) { - - if (watchdog) { - barrier->watchdog_pending = 1; - } - - // The thread must pend here - - rc = KERN_SEMAPHORE_PEND((KERN_SEMAPHORE *)(barrier->entry_sem), - KERN_WAIT_FOREVER); - if (rc) { - goto exit_critical; - } - - } else { - - // The barrier condition is met - or the watchdog thread is blocked - // here. The entry and exit semaphores and counts are swapped. The - // callback is marked to be called. - - // If the barrier is used incorrectly, or threads are deleted without - // adjusting the barrier target count then the following condition - // could become true, which could lead to bad behavior. - - if (barrier->exit_count != 0) { - KERN_PANIC(SYNC_BARRIER_INVARIANT); - } - - barrier->entry_count--; // Undo preincrement above - barrier->watchdog_pending = 0; - - temp_sem = (KERN_SEMAPHORE *)(barrier->exit_sem); - barrier->exit_sem = barrier->entry_sem; - barrier->entry_sem = temp_sem; - - barrier->exit_count = barrier->entry_count; - barrier->entry_count = 0; - - barrier->run_callback = 1; - } - - // This thread either continues to run or just woke up after having - // blocked at the barrier. The current thread makes the next thread (if - // any) runnable as well. Normally the current thread will be of a higher - // priority than any blocked threads, so no context switch will occur. The - // thread that satisfies the barrier condition \e will cause a context - // switch here, unless it just happens to be the highest priority thread - // in the barrier group. - - if (barrier->exit_count != 0) { - barrier->exit_count--; - rc = KERN_SEMAPHORE_POST((KERN_SEMAPHORE *)(barrier->exit_sem)); - } - -exit_critical: - - if (rc) { - KERN_CRITICAL_SECTION_EXIT(&ctx); - return rc; - } - - // In the case of a satisfied barrier condition, the first thread to exit - // the critical section will be the higest priority thread blocked at the - // barrier. This thread is tasked with executing the callback, outside of - // the critical section. - - run_callback = barrier->run_callback; - barrier->run_callback = 0; - if (run_callback) { - callback = barrier->callback; - arg = (void *)(barrier->arg); /* Cast away 'volatile' */ - } - - KERN_CRITICAL_SECTION_EXIT(&ctx); - - if (run_callback && callback) { - callback(arg); - } - - return 0; -} - - -/// Pend at a Barrier -/// -/// \param barrier An initialized barrier object -/// -/// A thread will pend at a barrier until \a count number of threads (supplied -/// in the call of barrier_create()) are pending. If \a count is 0 or 1, the -/// API always returns immediately. -/// -/// If barrier watchdog thread is being used (correctly), then the watchdog -/// will cause thread pending on the barrier to be released whenever all -/// threads in the group are blocked, regardless of whether some of the -/// group's threads are blocked elesewhere. -/// -/// \retval 0 Success -/// -/// \retval -SYNC_INVALID_OBJECT The \a barrier is NULL (0) -/// -/// Other errors may be returned by the embedded call of ssx_semephore_pend(). -/// In particular this API will fail if called outside of a thread context -/// since it requires blocking indefinitely on a semaphore. -/// -/// \bug The semaphore should be able to provide the number of pending threads -/// - which we should really be using here instead of the barrier counts. The -/// current implementation can produce some strange behavior if threads are -/// deleted. - -int -barrier_pend(Barrier *barrier) -{ - return _barrier_pend(barrier, 0); -} - - -/// Barrier watchdog thread -/// -/// \param arg A pointer to the Barrier object this thread should manage. -/// -/// A barrier_watchdog() thread is attached to a Barrier object, and forces -/// the barrier condition to be met whenever it runs. This thread is designed -/// to be mapped at a priority immediately below the priorities of a group of -/// threads that pend on the barrier. -/// -/// In this way, should every thread in the group become blocked, the watchdog -/// will allow any threads that are blocked on the barrier to run. If all the -/// threads are blocked elsewhere, then the watchdog blocks on the barrier, -/// and as soon as any thread pends again at the barrier the thread remains -/// runnable and the watchdog becomes runnable. -/// -/// The barrier_watchdog() thread is not required. Without the watchdog, -/// otherwise runnable threads in the barrier group will remain blocked on the -/// barrier as long as any of their cohorts remain blocked elsewhere. - -void -barrier_watchdog(void *arg) -{ - do { - _barrier_pend((Barrier *)arg, 1); - } while (1); -} diff --git a/src/lib/common/sync.h b/src/lib/common/sync.h deleted file mode 100644 index 5657c78..0000000 --- a/src/lib/common/sync.h +++ /dev/null @@ -1,167 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/lib/common/sync.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#ifndef __SYNC_H__ -#define __SYNC_H__ - -// $Id$ - -/// \file sync.h -/// \brief A library of higher-level synchronization primitives based on -/// low-level kernel services. -/// -/// The APIs provided here are currently based on SSX services, but the -/// specifications should allow applications to be fairly easily ported to -/// other environments if required. -/// -/// \todo Consider implementing a subset of the POSIX pthreads standards -/// instead of these non-standard synchronization primitives. Ideally all -/// synchronization primitives would be part of the SSX kernel so that they -/// would correctly handle thread suspension and deletion while pending. - -#include "kernel.h" - -// Error/panic codes - -#define SYNC_INVALID_OBJECT 0x00896201 -#define SYNC_INVALID_ARGUMENT 0x00896202 -#define SYNC_BARRIER_PEND_TIMED_OUT 0x00896203 -#define SYNC_BARRIER_OVERFLOW 0x00896204 -#define SYNC_BARRIER_UNDERFLOW 0x00896205 -#define SYNC_BARRIER_INVARIANT 0x00896206 -#define SYNC_SHARED_UNDERFLOW 0x00896207 - -//////////////////////////////////////////////////////////////////////////// -// Barrier -//////////////////////////////////////////////////////////////////////////// - -typedef void (*BarrierCallback)(void *); - -/// A thread barrier object -/// -/// A Barrier allows multiple threads to pend until a group of threads are all -/// pending at the barrier. Once all threads are pending at the barrier, all -/// threads are released again for execution. The barrier guarantees that -/// once released, lower-priority threads will have the chance to execute -/// before the barrier condition is satisfied again. Thus the Barrier can be -/// used as a form of fair scheduling for a group of threads that execute in a -/// loop of doing work followed by pending at the barrier. -/// -/// Although the barrier guarantees fairness, it can not by itself guarantee -/// progress. If several threads in a barrier group are -/// pending at the barrier while other threads in the group are blocked away -/// from the barrier, the threads at the barrier should be running (if allowed -/// by the priority mappings etc.). The only way to guarantee constant -/// progress by any unblocked thread in a group is to created another, -/// 'watchdog' thread that has lower priority than the other threads in the -/// group. The watchdog thread only executes when all threads in the group -/// are blocked, and ensures progress. This implementation provides a -/// watchdog thread routine as barrier_watchdog(). -/// -/// Normally the threads in a barrier group will be assigned consecutive -/// priorities - otherwise various forms of priority inversion can arise. The -/// watchdog thread, if any, will normally be assigned the priority -/// immediately lower than the lowest priority thread in the group. -/// -/// The Barrier object supports an optional callback function. The callback -/// (with the customary single (void *) parameter) is made when the barrier -/// condition is met, in the thread context of the first (highest priority) -/// thread to exit the barrier. The callback is made inside the barrier_pend() -/// call, but outside of a critical section. The specification of the callback -/// is not part of the barrier_create() call, but is provided later by the -/// barrier_callback_set() call. A NULL (0) callback (the default) is ignored. -/// -/// NB: All barrier APIs (other than barrier_create()) must be made from -/// thread mode - they will fail if called from interrupt handlers or before -/// threads have started. - -typedef struct Barrier { - - /// Semaphore array; see \a entry_sem and \a exit_sem; - KERN_SEMAPHORE sem[2]; - - /// The entry semaphore. - /// - /// Threads pending at the barrier initially block here. Once all of the - /// threads in the group are pending here, the entry and exit semaphores - /// are swapped and threads are released (in priority order) from the new - /// exit semaphore. - volatile KERN_SEMAPHORE *entry_sem; - - /// The exit semaphore. - volatile KERN_SEMAPHORE *exit_sem; - - /// The current count of threads pending at \a entry_sem. - volatile KERN_SEMAPHORE_COUNT entry_count; - - /// The current count of threads pending at \a exit_sem. - volatile KERN_SEMAPHORE_COUNT exit_count; - - /// The target number of threads required to release the barrier - volatile KERN_SEMAPHORE_COUNT target_count; - - /// A flag - Is the watchdog thread pending at the barrier? - volatile int watchdog_pending; - - /// Statistics - The number of times the watchdog has entered the barrier. - volatile uint32_t watchdog_entries; - - /// The barrier condition callback function - volatile BarrierCallback callback; - - /// The argument of the callback function - volatile void *arg; - - /// This flag is set to tell the first thread to exit the barrier to - /// execute the callback (if any). - volatile int run_callback; - -} Barrier; - -int -barrier_create(Barrier *barrier, KERN_SEMAPHORE_COUNT count); - -int -barrier_callback_set(Barrier *barrier, - BarrierCallback callback, - void *arg); - -int -barrier_pend(Barrier *barrier); - -void -barrier_watchdog(void *arg); - - -#endif // __SYNC_H__ - - - - - - - - - - |

