Mercurial > cgi-bin > hgwebdir.cgi > VMS > C_Libraries > Queue_impl
changeset 26:f5df9f4bed74
deprecated default brch
| author | kshalle |
|---|---|
| date | Mon, 13 Feb 2012 13:30:54 -0800 |
| parents | 27b341a31a21 |
| children | |
| files | .brch__default BlockingQueue.c BlockingQueue.h PrivateQueue.c PrivateQueue.h __brch__DEPRECATED_README |
| diffstat | 6 files changed, 8 insertions(+), 741 deletions(-) [+] |
line diff
1.1 --- a/.brch__default Sat Feb 11 20:39:26 2012 -0800 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,1 +0,0 @@ 1.4 -The default branch is for use with normal C code. Other branches specialize the library for use with VMS.. they may need VMS header files, and the working directory may be located at various different positions relative to the VMS implementation. 1.5 \ No newline at end of file
2.1 --- a/BlockingQueue.c Sat Feb 11 20:39:26 2012 -0800 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,470 +0,0 @@ 2.4 -/* 2.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 2.6 - * Licensed under GNU General Public License version 2 2.7 - * 2.8 - * Author: seanhalle@yahoo.com 2.9 - */ 2.10 - 2.11 - 2.12 -#include <stdio.h> 2.13 -#include <errno.h> 2.14 -#include <pthread.h> 2.15 -#include <stdlib.h> 2.16 -#include <sched.h> 2.17 - 2.18 -#include "BlockingQueue.h" 2.19 - 2.20 -#define INC(x) (++x == 1024) ? (x) = 0 : (x) 2.21 - 2.22 -#define SPINLOCK_TRIES 100000 2.23 - 2.24 -//=========================================================================== 2.25 -//Normal pthread Q 2.26 - 2.27 -PThdQueueStruc* makePThdQ() 2.28 - { 2.29 - PThdQueueStruc* retQ; 2.30 - int retCode; 2.31 - retQ = (PThdQueueStruc *) malloc( sizeof( PThdQueueStruc ) ); 2.32 - 2.33 - 2.34 - retCode = 2.35 - pthread_mutex_init( &retQ->mutex_t, NULL); 2.36 - if(retCode){perror("Error in creating mutex:"); exit(1);} 2.37 - 2.38 - retCode = pthread_cond_init ( &retQ->cond_w_t, NULL); 2.39 - if(retCode){perror("Error in creating cond_var:"); exit(1);} 2.40 - 2.41 - retCode = pthread_cond_init ( &retQ->cond_r_t, NULL); 2.42 - if(retCode){perror("Error in creating cond_var:"); exit(1);} 2.43 - 2.44 - retQ->count = 0; 2.45 - retQ->readPos = 0; 2.46 - retQ->writePos = 0; 2.47 - retQ->w_empty = 0; 2.48 - retQ->w_full = 0; 2.49 - 2.50 - return retQ; 2.51 - } 2.52 - 2.53 -void * readPThdQ( PThdQueueStruc *Q ) 2.54 - { void *ret; 2.55 - int retCode, wt; 2.56 - pthread_mutex_lock( &Q->mutex_t ); 2.57 - { 2.58 - while( Q -> count == 0 ) 2.59 - { Q -> w_empty = 1; 2.60 - retCode = 2.61 - pthread_cond_wait( &Q->cond_r_t, &Q->mutex_t ); 2.62 - if( retCode ){ perror("Thread wait error: "); exit(1); } 2.63 - } 2.64 - Q -> w_empty = 0; 2.65 - Q -> count -= 1; 2.66 - ret = Q->data[ Q->readPos ]; 2.67 - INC( Q->readPos ); 2.68 - wt = Q -> w_full; 2.69 - Q -> w_full = 0; 2.70 - } 2.71 - pthread_mutex_unlock( &Q->mutex_t ); 2.72 - if (wt) 2.73 - pthread_cond_signal( &Q->cond_w_t ); 2.74 - 2.75 - //printf("Q out: %d\n", ret); 2.76 - return( ret ); 2.77 - } 2.78 - 2.79 -void writePThdQ( void * in, PThdQueueStruc* Q ) 2.80 - { 2.81 - int status, wt; 2.82 - //printf("Q in: %d\n", in); 2.83 - 2.84 - pthread_mutex_lock( &Q->mutex_t ); 2.85 - { 2.86 - while( Q->count >= 1024 ) 2.87 - { 2.88 - Q -> w_full = 1; 2.89 - status = pthread_cond_wait( &Q->cond_w_t, &Q->mutex_t ); 2.90 - if (status != 0) 2.91 - { perror("Thread wait error: "); 2.92 - exit(1); 2.93 - } 2.94 - } 2.95 - 2.96 - Q -> w_full = 0; 2.97 - Q->count += 1; 2.98 - Q->data[ Q->writePos ] = in; 2.99 - INC( Q->writePos ); 2.100 - wt = Q -> w_empty; 2.101 - Q -> w_empty = 0; 2.102 - } 2.103 - 2.104 - pthread_mutex_unlock( &Q->mutex_t ); 2.105 - if( wt ) pthread_cond_signal( &Q->cond_r_t ); 2.106 - } 2.107 - 2.108 - 2.109 -//=========================================================================== 2.110 -// multi reader multi writer fast Q via CAS 2.111 -#ifndef _GNU_SOURCE 2.112 -#define _GNU_SOURCE 2.113 - 2.114 -/*This is a blocking queue, but it uses CAS instr plus yield() when empty 2.115 - * or full 2.116 - *It uses CAS because it's meant to have more than one reader and more than 2.117 - * one writer. 2.118 - */ 2.119 - 2.120 -CASQueueStruc* makeCASQ() 2.121 - { 2.122 - CASQueueStruc* retQ; 2.123 - retQ = (CASQueueStruc *) malloc( sizeof( CASQueueStruc ) ); 2.124 - 2.125 - retQ->insertLock = UNLOCKED; 2.126 - retQ->extractLock= UNLOCKED; 2.127 - //TODO: check got pointer syntax right 2.128 - retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty 2.129 - retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be 2.130 - retQ->endOfData = &(retQ->startOfData[1023]); 2.131 - 2.132 - return retQ; 2.133 - } 2.134 - 2.135 - 2.136 -void* readCASQ( CASQueueStruc* Q ) 2.137 - { void *out = 0; 2.138 - int tries = 0; 2.139 - void **startOfData = Q->startOfData; 2.140 - void **endOfData = Q->endOfData; 2.141 - 2.142 - int gotLock = FALSE; 2.143 - 2.144 - while( TRUE ) 2.145 - { //this intrinsic returns true if the lock held "UNLOCKED", in which 2.146 - // case it now holds "LOCKED" -- if it already held "LOCKED", then 2.147 - // gotLock is FALSE 2.148 - gotLock = 2.149 - __sync_bool_compare_and_swap( &(Q->extractLock), UNLOCKED, LOCKED ); 2.150 - //NOTE: checked assy, and it does lock correctly.. 2.151 - if( gotLock ) 2.152 - { 2.153 - void **insertPos = Q->insertPos; 2.154 - void **extractPos = Q->extractPos; 2.155 - 2.156 - //if not empty -- extract just below insert when empty 2.157 - if( insertPos - extractPos != 1 && 2.158 - !(extractPos == endOfData && insertPos == startOfData)) 2.159 - { //move before read 2.160 - if( extractPos == endOfData ) //write new pos exactly once, correctly 2.161 - { Q->extractPos = startOfData; //can't overrun then fix it 'cause 2.162 - } // other thread might read bad pos 2.163 - else 2.164 - { Q->extractPos++; 2.165 - } 2.166 - out = *(Q->extractPos); 2.167 - Q->extractLock = UNLOCKED; 2.168 - return out; 2.169 - } 2.170 - else //Q is empty 2.171 - { Q->extractLock = UNLOCKED;//empty, so release lock for others 2.172 - } 2.173 - } 2.174 - //Q is busy or empty 2.175 - tries++; 2.176 - if( tries > SPINLOCK_TRIES ) pthread_yield(); //not reliable 2.177 - } 2.178 - } 2.179 - 2.180 -void writeCASQ( void * in, CASQueueStruc* Q ) 2.181 - { 2.182 - int tries = 0; 2.183 - //TODO: need to make Q volatile? Want to do this Q in assembly! 2.184 - //Have no idea what GCC's going to do to this code 2.185 - void **startOfData = Q->startOfData; 2.186 - void **endOfData = Q->endOfData; 2.187 - 2.188 - int gotLock = FALSE; 2.189 - 2.190 - while( TRUE ) 2.191 - { //this intrinsic returns true if the lock held "UNLOCKED", in which 2.192 - // case it now holds "LOCKED" -- if it already held "LOCKED", then 2.193 - // gotLock is FALSE 2.194 - gotLock = 2.195 - __sync_bool_compare_and_swap( &(Q->insertLock), UNLOCKED, LOCKED ); 2.196 - if( gotLock ) 2.197 - { 2.198 - void **insertPos = Q->insertPos; 2.199 - void **extractPos = Q->extractPos; 2.200 - 2.201 - //check if room to insert.. can't use a count variable 2.202 - // 'cause both insertor Thd and extractor Thd would write it 2.203 - if( extractPos - insertPos != 1 && 2.204 - !(insertPos == endOfData && extractPos == startOfData)) 2.205 - { *(Q->insertPos) = in; //insert before move 2.206 - if( insertPos == endOfData ) 2.207 - { Q->insertPos = startOfData; 2.208 - } 2.209 - else 2.210 - { Q->insertPos++; 2.211 - } 2.212 - Q->insertLock = UNLOCKED; 2.213 - return; 2.214 - } 2.215 - else //Q is full 2.216 - { Q->insertLock = UNLOCKED;//full, so release lock for others 2.217 - } 2.218 - } 2.219 - tries++; 2.220 - if( tries > SPINLOCK_TRIES ) pthread_yield(); //not reliable 2.221 - } 2.222 - } 2.223 - 2.224 -#endif //_GNU_SOURCE 2.225 - 2.226 - 2.227 -//=========================================================================== 2.228 -//Single reader single writer super fast Q.. no atomic instrs.. 2.229 - 2.230 - 2.231 -/*This is a blocking queue, but it uses no atomic instructions, just does 2.232 - * yield() when empty or full 2.233 - * 2.234 - *It doesn't need any atomic instructions because only a single thread 2.235 - * extracts and only a single thread inserts, and it has no locations that 2.236 - * are written by both. It writes before moving and moves before reading, 2.237 - * and never lets write position and read position be the same, so dis- 2.238 - * synchrony can only ever cause an unnecessary call to yield(), never a 2.239 - * wrong value (by monotonicity of movement of pointers, plus single writer 2.240 - * to pointers, plus sequence of write before change pointer, plus 2.241 - * assumptions that if thread A semantically writes X before Y, then thread 2.242 - * B will see the writes in that order.) 2.243 - */ 2.244 - 2.245 -SRSWQueueStruc* makeSRSWQ() 2.246 - { 2.247 - SRSWQueueStruc* retQ; 2.248 - retQ = (SRSWQueueStruc *) malloc( sizeof( SRSWQueueStruc ) ); 2.249 - memset( retQ->startOfData, 0, 1024 * sizeof(void *) ); 2.250 - 2.251 - retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty 2.252 - retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be 2.253 - retQ->endOfData = &(retQ->startOfData[1023]); 2.254 - 2.255 - return retQ; 2.256 - } 2.257 - 2.258 -void 2.259 -freeSRSWQ( SRSWQueueStruc* Q ) 2.260 - { 2.261 - free( Q ); 2.262 - } 2.263 - 2.264 -void* readSRSWQ( SRSWQueueStruc* Q ) 2.265 - { void *out = 0; 2.266 - int tries = 0; 2.267 - 2.268 - while( TRUE ) 2.269 - { 2.270 - if( Q->insertPos - Q->extractPos != 1 && 2.271 - !(Q->extractPos == Q->endOfData && Q->insertPos == Q->startOfData)) 2.272 - { if( Q->extractPos >= Q->endOfData ) Q->extractPos = Q->startOfData; 2.273 - else Q->extractPos++; //move before read 2.274 - out = *(Q->extractPos); 2.275 - return out; 2.276 - } 2.277 - //Q is empty 2.278 - tries++; 2.279 - if( tries > SPINLOCK_TRIES ) pthread_yield(); 2.280 - } 2.281 - } 2.282 - 2.283 - 2.284 -void* readSRSWQ_NonBlocking( SRSWQueueStruc* Q ) 2.285 - { void *out = 0; 2.286 - int tries = 0; 2.287 - 2.288 - while( TRUE ) 2.289 - { 2.290 - if( Q->insertPos - Q->extractPos != 1 && 2.291 - !(Q->extractPos == Q->endOfData && Q->insertPos == Q->startOfData)) 2.292 - { Q->extractPos++; //move before read 2.293 - if( Q->extractPos > Q->endOfData ) Q->extractPos = Q->startOfData; 2.294 - out = *(Q->extractPos); 2.295 - return out; 2.296 - } 2.297 - //Q is empty 2.298 - tries++; 2.299 - if( tries > 10 ) return NULL; //long enough for writer to finish 2.300 - } 2.301 - } 2.302 - 2.303 - 2.304 -void writeSRSWQ( void * in, SRSWQueueStruc* Q ) 2.305 - { 2.306 - int tries = 0; 2.307 - 2.308 - while( TRUE ) 2.309 - { 2.310 - if( Q->extractPos - Q->insertPos != 1 && 2.311 - !(Q->insertPos == Q->endOfData && Q->extractPos == Q->startOfData)) 2.312 - { *(Q->insertPos) = in; //insert before move 2.313 - if( Q->insertPos >= Q->endOfData ) Q->insertPos = Q->startOfData; 2.314 - else Q->insertPos++; 2.315 - return; 2.316 - } 2.317 - //Q is full 2.318 - tries++; 2.319 - if( tries > SPINLOCK_TRIES ) pthread_yield(); 2.320 - } 2.321 - } 2.322 - 2.323 - 2.324 - 2.325 -//=========================================================================== 2.326 -//Single reader Multiple writer super fast Q.. no atomic instrs.. 2.327 - 2.328 - 2.329 -/*This is a blocking queue, but it uses no atomic instructions, just does 2.330 - * yield() when empty or full 2.331 - * 2.332 - *It doesn't need any atomic instructions because only a single thread 2.333 - * extracts and only a single thread inserts, and it has no locations that 2.334 - * are written by both. It writes before moving and moves before reading, 2.335 - * and never lets write position and read position be the same, so dis- 2.336 - * synchrony can only ever cause an unnecessary call to yield(), never a 2.337 - * wrong value (by monotonicity of movement of pointers, plus single writer 2.338 - * to pointers, plus sequence of write before change pointer, plus 2.339 - * assumptions that if thread A semantically writes X before Y, then thread 2.340 - * B will see the writes in that order.) 2.341 - * 2.342 - *The multi-writer version is implemented as a hierarchy. Each writer has 2.343 - * its own single-reader single-writer queue. The reader simply does a 2.344 - * round-robin harvesting from them. 2.345 - * 2.346 - *A writer must first register itself with the queue, and receives an ID back 2.347 - * It then uses that ID on each write operation. 2.348 - * 2.349 - *The implementation is: 2.350 - *Physically: 2.351 - * -] the SRMWQueueStruc holds an array of SRSWQueueStruc s 2.352 - * -] it also has read-pointer to the last queue a write was taken from. 2.353 - * 2.354 - *Action-Patterns: 2.355 - * -] To add a writer 2.356 - * --]] writer-thread calls addWriterToQ(), remember the ID it returns 2.357 - * --]] internally addWriterToQ does: 2.358 - * ---]]] if needs more room, makes a larger writer-array 2.359 - * ---]]] copies the old writer-array into the new 2.360 - * ---]]] makes a new SRSW queue an puts it into the array 2.361 - * ---]]] returns the index to the new SRSW queue as the ID 2.362 - * -] To write 2.363 - * --]] writer thread calls writeSRMWQ, passing the Q struc and its writer-ID 2.364 - * --]] this call may block, via repeated yield() calls 2.365 - * --]] internally, writeSRMWQ does: 2.366 - * ---]]] uses the writerID as index to get the SRSW queue for that writer 2.367 - * ---]]] performs writeQ on that queue (may block via repeated yield calls) 2.368 - * -] To Read 2.369 - * --]] reader calls readSRMWQ, passing the Q struc 2.370 - * --]] this call may block, via repeated yield() calls 2.371 - * --]] internally, readSRMWQ does: 2.372 - * ---]]] gets saved index of last SRSW queue read from 2.373 - * ---]]] increments index and gets indexed queue 2.374 - * ---]]] does a non-blocking read of that queue 2.375 - * ---]]] if gets something, saves index and returns that value 2.376 - * ---]]] if gets null, then goes to next queue 2.377 - * ---]]] if got null from all the queues then does yield() then tries again 2.378 - * 2.379 - *Note: "0" is used as the value null, so SRSW queues must only contain 2.380 - * pointers, and cannot use 0 as a valid pointer value. 2.381 - * 2.382 - */ 2.383 - 2.384 -SRMWQueueStruc* makeSRMWQ() 2.385 - { SRMWQueueStruc* retQ; 2.386 - 2.387 - retQ = (SRMWQueueStruc *) malloc( sizeof( SRMWQueueStruc ) ); 2.388 - 2.389 - retQ->numInternalQs = 0; 2.390 - retQ->internalQsSz = 10; 2.391 - retQ->internalQs = malloc( retQ->internalQsSz * sizeof(SRSWQueueStruc *)); 2.392 - 2.393 - retQ->lastQReadFrom = 0; 2.394 - 2.395 - return retQ; 2.396 - } 2.397 - 2.398 -/* ---]]] if needs more room, makes a larger writer-array 2.399 - * ---]]] copies the old writer-array into the new 2.400 - * ---]]] makes a new SRSW queue an puts it into the array 2.401 - * ---]]] returns the index to the new SRSW queue as the ID 2.402 - * 2.403 - *NOTE: assuming all adds are completed before any writes or reads are 2.404 - * performed.. otherwise, this needs to be re-done carefully, probably with 2.405 - * a lock. 2.406 - */ 2.407 -int addWriterToSRMWQ( SRMWQueueStruc* Q ) 2.408 - { int oldSz, i; 2.409 - SRSWQueueStruc * *oldArray; 2.410 - 2.411 - (Q->numInternalQs)++; 2.412 - if( Q->numInternalQs >= Q->internalQsSz ) 2.413 - { //full, so make bigger 2.414 - oldSz = Q->internalQsSz; 2.415 - oldArray = Q->internalQs; 2.416 - Q->internalQsSz *= 2; 2.417 - Q->internalQs = malloc( Q->internalQsSz * sizeof(SRSWQueueStruc *)); 2.418 - for( i = 0; i < oldSz; i++ ) 2.419 - { Q->internalQs[i] = oldArray[i]; 2.420 - } 2.421 - free( oldArray ); 2.422 - } 2.423 - Q->internalQs[ Q->numInternalQs - 1 ] = makeSRSWQ(); 2.424 - return Q->numInternalQs - 1; 2.425 - } 2.426 - 2.427 - 2.428 -/* ---]]] gets saved index of last SRSW queue read-from 2.429 - * ---]]] increments index and gets indexed queue 2.430 - * ---]]] does a non-blocking read of that queue 2.431 - * ---]]] if gets something, saves index and returns that value 2.432 - * ---]]] if gets null, then goes to next queue 2.433 - * ---]]] if got null from all the queues then does yield() then tries again 2.434 - */ 2.435 -void* readSRMWQ( SRMWQueueStruc* Q ) 2.436 - { SRSWQueueStruc *readQ; 2.437 - void *readValue = 0; 2.438 - int tries = 0; 2.439 - int QToReadFrom = 0; 2.440 - 2.441 - QToReadFrom = Q->lastQReadFrom; 2.442 - 2.443 - while( TRUE ) 2.444 - { QToReadFrom++; 2.445 - if( QToReadFrom >= Q->numInternalQs ) QToReadFrom = 0; 2.446 - readQ = Q->internalQs[ QToReadFrom ]; 2.447 - readValue = readSRSWQ_NonBlocking( readQ ); 2.448 - 2.449 - if( readValue != 0 ) //got a value, return it 2.450 - { Q->lastQReadFrom = QToReadFrom; 2.451 - return readValue; 2.452 - } 2.453 - else //SRSW Q just read is empty 2.454 - { //check if all queues have been tried 2.455 - if( QToReadFrom == Q->lastQReadFrom ) //all the queues tried & empty 2.456 - { tries++; //give a writer a chance to finish before yield 2.457 - if( tries > SPINLOCK_TRIES ) pthread_yield(); 2.458 - } 2.459 - } 2.460 - } 2.461 - } 2.462 - 2.463 - 2.464 -/* 2.465 - * ---]]] uses the writerID as index to get the SRSW queue for that writer 2.466 - * ---]]] performs writeQ on that queue (may block via repeated yield calls) 2.467 - */ 2.468 -void writeSRMWQ( void * in, SRMWQueueStruc* Q, int writerID ) 2.469 - { 2.470 - if( in == 0 ) printf( "error, wrote 0 to SRMW Q" );//TODO: throw an error 2.471 - 2.472 - writeSRSWQ( in, Q->internalQs[ writerID ] ); 2.473 - }
3.1 --- a/BlockingQueue.h Sat Feb 11 20:39:26 2012 -0800 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,92 +0,0 @@ 3.4 -/* 3.5 - * File: BlockingQueue.h 3.6 - * Author: SeanHalle@yahoo.com 3.7 - * 3.8 - * Created on November 11, 2009, 12:51 PM 3.9 - */ 3.10 - 3.11 -#ifndef _BLOCKINGQUEUE_H 3.12 -#define _BLOCKINGQUEUE_H 3.13 - 3.14 -#include "pthread.h" 3.15 - 3.16 - 3.17 -#define TRUE 1 3.18 -#define FALSE 0 3.19 - 3.20 -#define LOCKED 1 3.21 -#define UNLOCKED 0 3.22 - 3.23 - 3.24 -//========== pThreads based queue ========== 3.25 -/* It is the data that is shared so only need one mutex. */ 3.26 -typedef 3.27 -struct 3.28 - { pthread_mutex_t mutex_t; 3.29 - pthread_cond_t cond_w_t; 3.30 - pthread_cond_t cond_r_t; 3.31 - int count; 3.32 - int readPos; 3.33 - int writePos; 3.34 - void* data[1024]; //an array of pointers 3.35 - int w_empty; 3.36 - int w_full; 3.37 - } 3.38 -PThdQueueStruc; 3.39 - 3.40 -PThdQueueStruc* makePThdQ(); 3.41 -void* readPThdQ( PThdQueueStruc *Q ); 3.42 -void writePThdQ( void *in, PThdQueueStruc *Q ); 3.43 - 3.44 - 3.45 -//========== CAS based queue ========== 3.46 -typedef 3.47 -struct 3.48 - { volatile int insertLock; 3.49 - volatile int extractLock; 3.50 - volatile void* *insertPos; 3.51 - volatile void* *extractPos; 3.52 - void* startOfData[1024]; //data is pointers 3.53 - void* *endOfData; //set when make queue 3.54 - } 3.55 -CASQueueStruc; 3.56 - 3.57 -CASQueueStruc* makeCASQ(); 3.58 -void* readCASQ( CASQueueStruc *Q ); 3.59 -void writeCASQ( void *in, CASQueueStruc *Q ); 3.60 - 3.61 - 3.62 -//========= non-atomic instr based queue =========== 3.63 -typedef 3.64 -struct 3.65 - { void* *insertPos; 3.66 - void* *extractPos; 3.67 - void* startOfData[1024]; //data is pointers 3.68 - void* *endOfData; //set when make queue 3.69 - } 3.70 -SRSWQueueStruc; 3.71 - 3.72 -SRSWQueueStruc* makeSRSWQ(); 3.73 -void freeSRSWQ( SRSWQueueStruc* Q ); 3.74 -void* readSRSWQ( SRSWQueueStruc *Q ); 3.75 -void writeSRSWQ( void *in, SRSWQueueStruc *Q ); 3.76 - 3.77 - 3.78 -//========= non-atomic instr S R M W queue =========== 3.79 -typedef 3.80 -struct 3.81 - { int lastQReadFrom; 3.82 - int numInternalQs; 3.83 - int internalQsSz; 3.84 - SRSWQueueStruc* *internalQs; 3.85 - } 3.86 -SRMWQueueStruc; 3.87 - 3.88 -SRMWQueueStruc* makeSRMWQ(); 3.89 -int addWriterToSRMWQ( SRMWQueueStruc *Q ); 3.90 -void* readSRMWQ( SRMWQueueStruc *Q ); 3.91 -void writeSRMWQ( void *in, SRMWQueueStruc *Q, int writerID ); 3.92 - 3.93 - 3.94 -#endif /* _BLOCKINGQUEUE_H */ 3.95 -
4.1 --- a/PrivateQueue.c Sat Feb 11 20:39:26 2012 -0800 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,141 +0,0 @@ 4.4 -/* 4.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 4.6 - * Licensed under GNU General Public License version 2 4.7 - * 4.8 - * NOTE: this version of SRSW correct as of April 25, 2010 4.9 - * 4.10 - * Author: seanhalle@yahoo.com 4.11 - */ 4.12 - 4.13 - 4.14 -#include <stdio.h> 4.15 -#include <string.h> 4.16 -#include <errno.h> 4.17 -#include <stdlib.h> 4.18 - 4.19 -#include "PrivateQueue.h" 4.20 - 4.21 - 4.22 - 4.23 -//=========================================================================== 4.24 - 4.25 -/*This kind of queue is private to a single core at a time -- has no 4.26 - * synchronizations 4.27 - */ 4.28 - 4.29 -PrivQueueStruc* makePrivQ() 4.30 - { 4.31 - PrivQueueStruc* retQ; 4.32 - retQ = (PrivQueueStruc *) malloc( sizeof( PrivQueueStruc ) ); 4.33 - 4.34 - retQ->startOfData = malloc( 1024 * sizeof(void *) ); 4.35 - memset( retQ->startOfData, 0, 1024 * sizeof(void *) ); 4.36 - retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty 4.37 - retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be 4.38 - retQ->endOfData = &(retQ->startOfData[1023]); 4.39 - 4.40 - return retQ; 4.41 - } 4.42 - 4.43 - 4.44 -void 4.45 -enlargePrivQ( PrivQueueStruc *Q ) 4.46 - { int oldSize, newSize; 4.47 - void **oldStartOfData; 4.48 - 4.49 - oldSize = Q->endOfData - Q->startOfData; 4.50 - newSize = 2 * oldSize; 4.51 - oldStartOfData = Q->startOfData; 4.52 - Q->startOfData = malloc( newSize * sizeof(void *) ); 4.53 - memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *)); 4.54 - free(oldStartOfData); 4.55 - 4.56 - Q->extractPos = &(Q->startOfData[0]); //side by side == empty 4.57 - Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be 4.58 - Q->endOfData = &(Q->startOfData[newSize - 1]); 4.59 - } 4.60 - 4.61 - 4.62 -/*Returns NULL when queue is empty 4.63 - */ 4.64 -void* readPrivQ( PrivQueueStruc* Q ) 4.65 - { void *out = 0; 4.66 - void **startOfData = Q->startOfData; 4.67 - void **endOfData = Q->endOfData; 4.68 - 4.69 - void **insertPos = Q->insertPos; 4.70 - void **extractPos = Q->extractPos; 4.71 - 4.72 - //if not empty -- (extract is just below insert when empty) 4.73 - if( insertPos - extractPos != 1 && 4.74 - !(extractPos == endOfData && insertPos == startOfData)) 4.75 - { //move before read 4.76 - if( extractPos == endOfData ) //write new pos exactly once, correctly 4.77 - { Q->extractPos = startOfData; //can't overrun then fix it 'cause 4.78 - } // other thread might read bad pos 4.79 - else 4.80 - { Q->extractPos++; 4.81 - } 4.82 - out = *(Q->extractPos); 4.83 - return out; 4.84 - } 4.85 - //Q is empty 4.86 - return NULL; 4.87 - } 4.88 - 4.89 - 4.90 -/*Expands the queue size automatically when it's full 4.91 - */ 4.92 -void 4.93 -writePrivQ( void * in, PrivQueueStruc* Q ) 4.94 - { 4.95 - void **startOfData = Q->startOfData; 4.96 - void **endOfData = Q->endOfData; 4.97 - 4.98 - void **insertPos = Q->insertPos; 4.99 - void **extractPos = Q->extractPos; 4.100 - 4.101 -tryAgain: 4.102 - //Full? (insert is just below extract when full) 4.103 - if( extractPos - insertPos != 1 && 4.104 - !(insertPos == endOfData && extractPos == startOfData)) 4.105 - { *(Q->insertPos) = in; //insert before move 4.106 - if( insertPos == endOfData ) //write new pos exactly once, correctly 4.107 - { Q->insertPos = startOfData; 4.108 - } 4.109 - else 4.110 - { Q->insertPos++; 4.111 - } 4.112 - return; 4.113 - } 4.114 - //Q is full 4.115 - enlargePrivQ( Q ); 4.116 - goto tryAgain; 4.117 - } 4.118 - 4.119 - 4.120 -/*Returns false when the queue was full. 4.121 - * have option of calling make_larger_PrivQ to make more room, then try again 4.122 - */ 4.123 -int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q ) 4.124 - { 4.125 - void **startOfData = Q->startOfData; 4.126 - void **endOfData = Q->endOfData; 4.127 - 4.128 - void **insertPos = Q->insertPos; 4.129 - void **extractPos = Q->extractPos; 4.130 - 4.131 - if( extractPos - insertPos != 1 && 4.132 - !(insertPos == endOfData && extractPos == startOfData)) 4.133 - { *(Q->insertPos) = in; //insert before move 4.134 - if( insertPos == endOfData ) //write new pos exactly once, correctly 4.135 - { Q->insertPos = startOfData; 4.136 - } 4.137 - else 4.138 - { Q->insertPos++; 4.139 - } 4.140 - return TRUE; 4.141 - } 4.142 - //Q is full 4.143 - return FALSE; 4.144 - }
5.1 --- a/PrivateQueue.h Sat Feb 11 20:39:26 2012 -0800 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,37 +0,0 @@ 5.4 -/* 5.5 - * Copyright 2009 OpenSourceStewardshipFoundation.org 5.6 - * Licensed under GNU General Public License version 2 5.7 - * 5.8 - * Author: seanhalle@yahoo.com 5.9 - */ 5.10 - 5.11 -#ifndef _PRIVATE_QUEUE_H 5.12 -#define _PRIVATE_QUEUE_H 5.13 - 5.14 -#include <pthread.h> 5.15 - 5.16 -#define TRUE 1 5.17 -#define FALSE 0 5.18 - 5.19 -#define LOCKED 1 5.20 -#define UNLOCKED 0 5.21 - 5.22 - 5.23 -/* It is the data that is shared so only need one mutex. */ 5.24 -typedef struct 5.25 - { void **insertPos; 5.26 - void **extractPos; 5.27 - void **startOfData; //data is pointers 5.28 - void **endOfData; //set when alloc data 5.29 - } 5.30 -PrivQueueStruc; 5.31 - 5.32 - 5.33 -PrivQueueStruc* makePrivQ ( ); 5.34 -void* readPrivQ ( PrivQueueStruc *Q ); 5.35 -void writePrivQ( void *in, PrivQueueStruc *Q ); 5.36 -int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q ); //return 5.37 - // false when full 5.38 - 5.39 -#endif /* _PRIVATE_QUEUE_H */ 5.40 -
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/__brch__DEPRECATED_README Mon Feb 13 13:30:54 2012 -0800 6.3 @@ -0,0 +1,8 @@ 6.4 + 6.5 +There are two versions of the library -- one for pure C use, the other for use inside VMS or within applications written in a VMS-based language (IE, inside a top-level function or a call descendant of a top-level function) -- but only when the VMS is the "MC_shared" version. 6.6 + 6.7 +The reason is that VMS that uses shared memory on multicores moves the SlaveVPs around among cores. But, the libC and glibC malloc stores info at the top of the stack (a "clever" hack), for a speed improvement. So, when VMS manipulates the stack pointer, and/or moves Slaves to different cores, the "free" seg faults (that was FUN to figure out ; ) So, this version of VMS implements its own malloc. 6.8 + 6.9 +It is anticipated that the MC_split version, where each core has separate data, and messages are sent between cores, can handle malloc and free to use the glibC version. 6.10 + 6.11 +For now, update to the version of the library you wish to use..
