Scippy

SCIP

Solving Constraint Integer Programs

tpi_openmp.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file tpi_openmp.c
26 * @ingroup TASKINTERFACE
27 * @brief the interface functions for openmp
28 * @author Stephen J. Maher
29 * @author Leona Gottwald
30 * @author Marc Pfetsch
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34
35#include "tpi/tpi.h"
37#include "scip/pub_message.h"
38#include "scip/pub_misc.h"
39#include <omp.h>
40
41/* macros for direct access */
42
43/* lock */
44#define SCIPompInitLock(lock) (omp_init_lock(lock), SCIP_OKAY)
45#define SCIPompDestroyLock(lock) (omp_destroy_lock(lock))
46#define SCIPompAcquireLock(lock) (omp_set_lock(lock), SCIP_OKAY)
47#define SCIPompReleaseLock(lock) (omp_unset_lock(lock), SCIP_OKAY)
48
49/* condition */
50#define SCIPompInitCondition(condition) ( omp_init_lock(&(condition)->_lock), \
51 (condition)->_waiters = 0, (condition)->_waitnum = 0, (condition)->_signals = 0, SCIP_OKAY )
52#define SCIPompDestroyCondition(condition) do { assert((condition)->_waiters == 0); assert((condition)->_waitnum == 0); assert((condition)->_signals == 0); omp_destroy_lock(&(condition)->_lock); } while(0)
53
54
55/** struct containing lock */
57{
58 omp_lock_t lock;
59};
60
61/** struct for condition */
63{
64 omp_lock_t _lock;
65 int _waiters;
66 int _waitnum;
67 int _signals;
68};
69
70
71/** A job added to the queue */
73{
74 int jobid; /**< id to identify jobs from a common process */
75 struct SCIP_Job* nextjob; /**< pointer to the next job in the queue */
76 SCIP_RETCODE (*jobfunc)(void* args);/**< pointer to the job function */
77 void* args; /**< pointer to the function arguments */
78 SCIP_RETCODE retcode; /**< return code of the job */
79};
80
81/** the thread pool job queue */
83{
84 SCIP_JOB* firstjob; /**< pointer to the first job in the queue */
85 SCIP_JOB* lastjob; /**< pointer to the last job in the queue */
86 int njobs; /**< number of jobs in the queue */
87};
89
91{
92 SCIP_JOBQUEUE jobqueue; /**< queue of unprocessed jobs */
93 SCIP_JOB** currentjobs; /**< array with slot for each thread to store the currently running job */
94 int ncurrentjobs; /**< number of currently running jobs */
95 int nthreads; /**< number of threads */
96 SCIP_JOBQUEUE finishedjobs; /**< jobqueue containing the finished jobs */
97 omp_lock_t lock; /**< lock to protect this stucture from concurrent access */
98 SCIP_CONDITION jobfinished; /**< condition to signal if a job was finished */
99};
101
102static SCIP_JOBQUEUES* _jobqueues = NULL;
103
104
105/** create job queue */
106static
108 int nthreads, /**< the number of threads */
109 int qsize, /**< the queue size */
110 SCIP_Bool blockwhenfull /**< should the queue be blocked from new jobs when full */
111 )
112{
113 int i;
114
115 assert(nthreads >= 0);
116 assert(qsize >= 0);
117 SCIP_UNUSED( blockwhenfull );
118
119 /* allocting memory for the job queue */
120 SCIP_ALLOC( BMSallocMemory(&_jobqueues) );
121 _jobqueues->jobqueue.firstjob = NULL;
122 _jobqueues->jobqueue.lastjob = NULL;
123 _jobqueues->jobqueue.njobs = 0;
124 _jobqueues->finishedjobs.firstjob = NULL;
125 _jobqueues->finishedjobs.lastjob = NULL;
126 _jobqueues->finishedjobs.njobs = 0;
127 _jobqueues->ncurrentjobs = 0;
128
129 _jobqueues->nthreads = nthreads;
131
132 for( i = 0; i < nthreads; ++i )
133 _jobqueues->currentjobs[i] = NULL;
134
135 SCIP_CALL( SCIPompInitLock(&_jobqueues->lock) );
137
138 return SCIP_OKAY;
139}
140
141
142/** free job queue */
143static
145 void
146 )
147{
148 assert(_jobqueues != NULL);
149
150 SCIPompDestroyLock(&_jobqueues->lock);
152 BMSfreeMemoryArray(&_jobqueues->currentjobs);
153
154 BMSfreeMemory(&_jobqueues);
155
156 return SCIP_OKAY;
157}
158
159
160/** execute job */
161static
163 SCIP_JOB* job /**< the job to be executed in parallel */
164 )
165{
166 int threadnum;
167
168 threadnum = SCIPtpiGetThreadNum();
169
170 SCIP_CALL_ABORT( SCIPompAcquireLock(&_jobqueues->lock) );
171 _jobqueues->currentjobs[threadnum] = job;
172 SCIP_CALL_ABORT( SCIPompReleaseLock(&_jobqueues->lock) );
173
174 job->retcode = (*(job->jobfunc))(job->args);
175
176 SCIP_CALL_ABORT( SCIPompAcquireLock(&_jobqueues->lock) );
177 _jobqueues->ncurrentjobs--;
178 _jobqueues->currentjobs[threadnum] = NULL;
179
180 /* insert job into finished jobs */
181 if( _jobqueues->finishedjobs.njobs == 0 )
182 {
183 _jobqueues->finishedjobs.firstjob = job;
184 _jobqueues->finishedjobs.lastjob = job;
185 }
186 else
187 {
188 _jobqueues->finishedjobs.lastjob->nextjob = job;
189 _jobqueues->finishedjobs.lastjob = job;
190 }
191
192 ++_jobqueues->finishedjobs.njobs;
193
195
196 SCIP_CALL_ABORT( SCIPompReleaseLock(&_jobqueues->lock) );
197}
198
199/** wait for a condition */
201 SCIP_CONDITION* condition, /**< condition to wait for */
202 SCIP_LOCK* lock /**< corresponding lock */
203 )
204{
205 int waitnum;
206
208
209 SCIP_CALL( SCIPompAcquireLock(&condition->_lock) );
210 waitnum = ++condition->_waitnum;
211
212 ++condition->_waiters;
213
214 do
215 {
216 SCIP_CALL( SCIPompReleaseLock(&condition->_lock) );
217 #pragma omp taskyield
218 SCIP_CALL( SCIPompAcquireLock(&condition->_lock) );
219 }
220 while( condition->_signals < waitnum );
221
222 --condition->_waiters;
223
224 if( condition->_waiters == 0 )
225 {
226 condition->_signals = 0;
227 condition->_waitnum = 0;
228 }
229
230 SCIP_CALL( SCIPompReleaseLock(&condition->_lock) );
231
233
234 return SCIP_OKAY;
235}
236
237/** wait for a condition (direct access to lock) */
238static
240 SCIP_CONDITION* condition, /**< condition to wait for */
241 omp_lock_t* lock /**< corresponding lock */
242 )
243{
244 int waitnum;
245
247
248 SCIP_CALL( SCIPompAcquireLock(&condition->_lock) );
249 waitnum = ++condition->_waitnum;
250
251 ++condition->_waiters;
252
253 do
254 {
255 SCIP_CALL( SCIPompReleaseLock(&condition->_lock) );
256 #pragma omp taskyield
257 SCIP_CALL( SCIPompAcquireLock(&condition->_lock) );
258 }
259 while( condition->_signals < waitnum );
260
261 --condition->_waiters;
262
263 if( condition->_waiters == 0 )
264 {
265 condition->_signals = 0;
266 condition->_waitnum = 0;
267 }
268
269 SCIP_CALL( SCIPompReleaseLock(&condition->_lock) );
270
272
273 return SCIP_OKAY;
274}
275
276
277/** process jobs from job queue
278 *
279 * The job will only be added when the number of active jobs is equal to the number of threads.
280 * As such, there will always be number of threads + 1 tasks available for the scheduler to run.
281 */
282static
284 void
285 )
286{
287 SCIP_JOB* job;
288
289 SCIP_CALL_ABORT( SCIPompAcquireLock(&_jobqueues->lock) );
290
291 while( _jobqueues->ncurrentjobs == SCIPtpiGetNumThreads() )
292 {
293 SCIP_CALL_ABORT( SCIPompWaitCondition(&_jobqueues->jobfinished, &_jobqueues->lock) );
294 }
295
296 if( _jobqueues->jobqueue.njobs == 1 )
297 {
298 job = _jobqueues->jobqueue.firstjob;
299 _jobqueues->jobqueue.firstjob = NULL;
300 _jobqueues->jobqueue.lastjob = NULL;
301 --(_jobqueues->jobqueue.njobs);
302 }
303 else if( _jobqueues->jobqueue.njobs > 1 )
304 {
305 job = _jobqueues->jobqueue.firstjob;
306 _jobqueues->jobqueue.firstjob = job->nextjob;
307 --_jobqueues->jobqueue.njobs;
308 }
309 else
310 {
311 job = NULL;
312 }
313
314 ++(_jobqueues->ncurrentjobs);
315 SCIP_CALL_ABORT( SCIPompReleaseLock(&_jobqueues->lock) );
316
317 if( job )
318 {
319 executeJob(job);
320 }
321}
322
323
324/** adding a job to the job queue
325 *
326 * This gives some more flexibility in the handling of new jobs.
327 * IMPORTANT: This function MUST be called from within a mutex.
328 */
329static
331 SCIP_JOB* newjob
332 )
333{
334 /* @todo we want to work out what to do with a full job queue. Is there a problem if the limit is hit? */
335 /* @note it is important to have a queuesize. This will stop the code submitting infinitely many jobs. */
336 assert(newjob != NULL);
337
338 newjob->nextjob = NULL;
339
340 /* This function queries the current job list. This could change by other threads writing to the list. So a lock is
341 * required to ensure that the current joblist remains static. */
342 SCIP_CALL( SCIPompAcquireLock(&_jobqueues->lock) );
343
344 /* checking the status of the job queue */
345 if( _jobqueues->ncurrentjobs == SCIPtpiGetNumThreads() )
346 {
347 if( _jobqueues->jobqueue.njobs == 0 )
348 {
349 _jobqueues->jobqueue.firstjob = newjob;
350 _jobqueues->jobqueue.lastjob = newjob;
351 }
352 else /* it is assumed that the jobqueue is not full */
353 {
354 _jobqueues->jobqueue.lastjob->nextjob = newjob;
355 _jobqueues->jobqueue.lastjob = newjob;
356 }
357
358 _jobqueues->jobqueue.njobs++;
359
360 SCIP_CALL( SCIPompReleaseLock(&_jobqueues->lock) );
361
362 #pragma omp task
364 }
365 else
366 {
367 assert(_jobqueues->ncurrentjobs < SCIPtpiGetNumThreads());
368
369 _jobqueues->ncurrentjobs++;
370
371 SCIP_CALL( SCIPompReleaseLock(&_jobqueues->lock) );
372 /* running the new job */
373 #pragma omp task firstprivate(newjob)
374 executeJob(newjob);
375 }
376
377 return SCIP_OKAY;
378}
379
380
381/** signal a condition */
383 SCIP_CONDITION* condition /**< condition to signal */
384 )
385{
386 assert( condition != NULL );
387
388 SCIP_CALL( SCIPompAcquireLock(&condition->_lock) );
389
390 if( condition->_waitnum > condition->_signals )
391 ++condition->_signals;
392
393 SCIP_CALL( SCIPompReleaseLock(&condition->_lock) );
394
395 return SCIP_OKAY;
396}
397
398
399/** broadcase a condition */
401 SCIP_CONDITION* condition /**< broadcast a condition */
402 )
403{
404 assert( condition != NULL );
405
406 SCIP_CALL( SCIPompAcquireLock(&condition->_lock) );
407 condition->_signals = condition->_waitnum;
408 SCIP_CALL( SCIPompReleaseLock(&condition->_lock) );
409
410 return SCIP_OKAY;
411}
412
413
414
415/** returns the number of threads */
417 )
418{
419 return omp_get_num_threads();
420}
421
422/** returns the thread number */
424 )
425{
426 return omp_get_thread_num();
427}
428
429/** creates a job for parallel processing */
431 SCIP_JOB** job, /**< pointer to the job that will be created */
432 int jobid, /**< the id for the current job */
433 SCIP_RETCODE (*jobfunc)(void* args),/**< pointer to the job function */
434 void* jobarg /**< the job's argument */
435 )
436{
438
439 (*job)->jobid = jobid;
440 (*job)->jobfunc = jobfunc;
441 (*job)->args = jobarg;
442 (*job)->nextjob = NULL;
443
444 return SCIP_OKAY;
445}
446
447/** get a new job id for the new set of submitted jobs */
449 void
450 )
451{
452 static int currentjobid = 0;
453 int jobid;
454
455 #pragma omp atomic capture
456 jobid = ++currentjobid;
457
458 return jobid;
459}
460
461/** submit a job for parallel processing; the return value is a globally defined status */
463 SCIP_JOB* job, /**< pointer to the job to be submitted */
464 SCIP_SUBMITSTATUS* status /**< pointer to store the submit status */
465 )
466{
467 assert(_jobqueues != NULL);
468
469 *status = SCIP_SUBMIT_SUCCESS;
471
472 return SCIP_OKAY;
473}
474
475
476/** check whether a job is running */
477static
479 int jobid /**< job id to check */
480 )
481{
482 int i;
483
484 if( _jobqueues->ncurrentjobs > 0 )
485 {
486 for( i = 0; i < _jobqueues->nthreads; ++i )
487 {
488 if( _jobqueues->currentjobs[i] != NULL && _jobqueues->currentjobs[i]->jobid == jobid )
489 return TRUE;
490 }
491 }
492
493 return FALSE;
494}
495
496
497/** check whether a job is waiting */
498static
500 int jobid /**< job id to check */
501 )
502{
503 if( _jobqueues->jobqueue.njobs > 0 )
504 {
505 SCIP_JOB* currjob;
506 currjob = _jobqueues->jobqueue.firstjob;
507
508 do
509 {
510 if( currjob->jobid == jobid )
511 return TRUE;
512
513 if( currjob == _jobqueues->jobqueue.lastjob )
514 break;
515
516 currjob = currjob->nextjob;
517 }
518 while( TRUE ); /*lint !e506*/
519 }
520
521 return FALSE;
522}
523
524
525/** blocks until all jobs of the given jobid have finished
526 * and then returns the smallest SCIP_RETCODE of all the jobs */
528 int jobid /**< the jobid of the jobs to wait for */
529 )
530{
531 SCIP_RETCODE retcode;
532
533 retcode = SCIP_OKAY;
534 SCIP_CALL( SCIPompAcquireLock(&_jobqueues->lock) );
535
536 while( isJobRunning(jobid) || isJobWaiting(jobid) )
537 {
538 SCIP_CALL( SCIPompWaitCondition(&_jobqueues->jobfinished, &_jobqueues->lock) );
539 }
540
541 if( _jobqueues->finishedjobs.njobs > 0 )
542 {
543 SCIP_JOB* currjob = _jobqueues->finishedjobs.firstjob;
544 SCIP_JOB* prevjob = NULL;
545
546 /* finding the location of the processed job in the currentjobs queue */
547 do
548 {
549 if( currjob->jobid == jobid )
550 {
551 SCIP_JOB* nextjob;
552
553 /* if the job has the right jobid collect its retcode, remove it from the finished job list, and free it */
554 retcode = MIN(retcode, currjob->retcode);
555
556 /* removing the finished job from finished jobs list */
557 if( currjob == _jobqueues->finishedjobs.firstjob )
558 _jobqueues->finishedjobs.firstjob = currjob->nextjob;
559 else
560 {
561 if( prevjob != NULL )
562 prevjob->nextjob = currjob->nextjob; /*lint !e613*/
563 }
564
565 if( currjob == _jobqueues->finishedjobs.lastjob )
566 _jobqueues->finishedjobs.lastjob = prevjob;
567
568 _jobqueues->finishedjobs.njobs--;
569
570 /* update currjob and free finished job; prevjob stays the same */
571 nextjob = currjob->nextjob;
572 BMSfreeMemory(&currjob);
573 currjob = nextjob;
574 }
575 else
576 {
577 prevjob = currjob;
578 currjob = prevjob->nextjob;
579 }
580 }
581 while( prevjob != _jobqueues->finishedjobs.lastjob );
582 }
583 else
584 {
585 /* given jobid was not submitted */
586 printf("err1");
587 retcode = SCIP_ERROR;
588 }
589
590 SCIP_CALL_ABORT( SCIPompReleaseLock(&_jobqueues->lock) );
591
592 return retcode;
593}
594
595/** initializes tpi */
597 int nthreads, /**< the number of threads to be used */
598 int queuesize, /**< the size of the queue */
599 SCIP_Bool blockwhenfull /**< should the queue block when full */
600 )
601{
602 omp_set_num_threads(nthreads);
603 assert(_jobqueues == NULL);
604
605 SCIP_CALL( createJobQueue(nthreads, queuesize, blockwhenfull) );
606
607 return SCIP_OKAY;
608}
609
610/** deinitializes tpi */
612 void
613 )
614{
615 assert(_jobqueues != NULL);
616 assert(_jobqueues->finishedjobs.njobs == 0);
617 assert(_jobqueues->jobqueue.njobs == 0);
618 assert(_jobqueues->ncurrentjobs == 0);
619
621
622 return SCIP_OKAY;
623}
624
625
626/*
627 * locks
628 */
629
630/** initializes the given lock */
632 SCIP_LOCK** lock /**< the lock */
633 )
634{
635 assert(lock != NULL);
636
638 omp_init_lock(&(*lock)->lock);
639 return SCIP_OKAY;
640}
641
642/** destroys the given lock */
644 SCIP_LOCK** lock /**< the lock */
645 )
646{
647 assert(lock != NULL);
648
649 omp_destroy_lock(&(*lock)->lock);
651}
652
653/** acquires the given lock */
655 SCIP_LOCK* lock /**< the lock */
656 )
657{
658 omp_set_lock(&lock->lock);
659 return SCIP_OKAY;
660}
661
662/** releases the given lock */
664 SCIP_LOCK* lock /**< the lock */
665 )
666{
667 omp_unset_lock(&lock->lock);
668 return SCIP_OKAY;
669}
670
671
672/*
673 * conditions
674 */
675
676/** initializes the given condition variable */
678 SCIP_CONDITION** condition /**< condition to be created and initialized */
679 )
680{
681 assert(condition != NULL);
682
683 SCIP_ALLOC( BMSallocMemory(condition) );
684
685 omp_init_lock(&(*condition)->_lock);
686 (*condition)->_waiters = 0;
687 (*condition)->_waitnum = 0;
688 (*condition)->_signals = 0;
689
690 return SCIP_OKAY;
691}
692
693/** destroys the given condition variable */
695 SCIP_CONDITION** condition /**< condition to be destroyed and freed */
696 )
697{
698 assert((*condition)->_waiters == 0);
699 assert((*condition)->_waitnum == 0);
700 assert((*condition)->_signals == 0);
701
702 omp_destroy_lock(&(*condition)->_lock);
703
704 BMSfreeMemory(condition);
705}
706
707/** indicate whether a working TPI is available */
709{
710 return TRUE;
711}
712
713/** get name of library that the TPI interfaces to */
715 char* name, /**< buffer to store name */
716 int namesize /**< length of name buffer */
717 )
718{
719 assert(name != NULL);
720
721 (void) SCIPsnprintf(name, namesize, "OpenMP %d", _OPENMP); /*lint !e40*/
722}
723
724/** get description of library that the TPI interfaces to */
726 char* desc, /**< buffer to store description */
727 int descsize /**< length of description */
728 )
729{
730 assert(desc != NULL);
731
732 (void) SCIPsnprintf(desc, descsize, "shared-memory multiprocessing library (openmp.org)");
733}
#define NULL
Definition: def.h:266
#define SCIP_UNUSED(x)
Definition: def.h:427
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:242
#define SCIP_ALLOC(x)
Definition: def.h:384
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL_ABORT(x)
Definition: def.h:352
#define SCIP_CALL(x)
Definition: def.h:373
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10880
memory allocation routines
#define BMSfreeMemory(ptr)
Definition: memory.h:145
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:123
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:147
#define BMSallocMemory(ptr)
Definition: memory.h:118
public methods for message output
public data structures and miscellaneous methods
SCIP_JOB * lastjob
Definition: tpi_openmp.c:85
SCIP_JOB * firstjob
Definition: tpi_openmp.c:84
SCIP_JOB ** currentjobs
Definition: tpi_openmp.c:93
SCIP_JOBQUEUE finishedjobs
Definition: tpi_openmp.c:96
SCIP_JOBQUEUE jobqueue
Definition: tpi_openmp.c:92
SCIP_CONDITION jobfinished
Definition: tpi_openmp.c:98
omp_lock_t lock
Definition: tpi_openmp.c:97
SCIP_RETCODE retcode
Definition: tpi_openmp.c:78
struct SCIP_Job * nextjob
Definition: tpi_openmp.c:75
void * args
Definition: tpi_openmp.c:77
SCIP_RETCODE(* jobfunc)(void *args)
Definition: tpi_openmp.c:76
int jobid
Definition: tpi_openmp.c:74
omp_lock_t lock
Definition: tpi_openmp.c:58
the type definitions for the SCIP parallel interface
#define SCIPompInitLock(lock)
Definition: tpi_openmp.c:44
SCIP_Bool SCIPtpiIsAvailable(void)
Definition: tpi_openmp.c:708
#define SCIPompAcquireLock(lock)
Definition: tpi_openmp.c:46
SCIP_RETCODE SCIPtpiWaitCondition(SCIP_CONDITION *condition, SCIP_LOCK *lock)
Definition: tpi_openmp.c:200
SCIP_RETCODE SCIPtpiCreateJob(SCIP_JOB **job, int jobid, SCIP_RETCODE(*jobfunc)(void *args), void *jobarg)
Definition: tpi_openmp.c:430
SCIP_RETCODE SCIPtpiSignalCondition(SCIP_CONDITION *condition)
Definition: tpi_openmp.c:382
static SCIP_RETCODE jobQueueAddJob(SCIP_JOB *newjob)
Definition: tpi_openmp.c:330
SCIP_RETCODE SCIPtpiAcquireLock(SCIP_LOCK *lock)
Definition: tpi_openmp.c:654
#define SCIPompReleaseLock(lock)
Definition: tpi_openmp.c:47
#define SCIPompDestroyLock(lock)
Definition: tpi_openmp.c:45
int SCIPtpiGetNumThreads()
Definition: tpi_openmp.c:416
SCIP_RETCODE SCIPtpiExit(void)
Definition: tpi_openmp.c:611
static void executeJob(SCIP_JOB *job)
Definition: tpi_openmp.c:162
SCIP_RETCODE SCIPtpiBroadcastCondition(SCIP_CONDITION *condition)
Definition: tpi_openmp.c:400
static SCIP_RETCODE freeJobQueue(void)
Definition: tpi_openmp.c:144
static void jobQueueProcessJob(void)
Definition: tpi_openmp.c:283
SCIP_RETCODE SCIPtpiSubmitJob(SCIP_JOB *job, SCIP_SUBMITSTATUS *status)
Definition: tpi_openmp.c:462
void SCIPtpiDestroyLock(SCIP_LOCK **lock)
Definition: tpi_openmp.c:643
void SCIPtpiGetLibraryDesc(char *desc, int descsize)
Definition: tpi_openmp.c:725
SCIP_RETCODE SCIPtpiCollectJobs(int jobid)
Definition: tpi_openmp.c:527
static SCIP_RETCODE SCIPompWaitCondition(SCIP_CONDITION *condition, omp_lock_t *lock)
Definition: tpi_openmp.c:239
static SCIP_RETCODE createJobQueue(int nthreads, int qsize, SCIP_Bool blockwhenfull)
Definition: tpi_openmp.c:107
static SCIP_Bool isJobRunning(int jobid)
Definition: tpi_openmp.c:478
static SCIP_Bool isJobWaiting(int jobid)
Definition: tpi_openmp.c:499
void SCIPtpiDestroyCondition(SCIP_CONDITION **condition)
Definition: tpi_openmp.c:694
#define SCIPompDestroyCondition(condition)
Definition: tpi_openmp.c:52
int SCIPtpiGetNewJobID(void)
Definition: tpi_openmp.c:448
void SCIPtpiGetLibraryName(char *name, int namesize)
Definition: tpi_openmp.c:714
SCIP_RETCODE SCIPtpiInitLock(SCIP_LOCK **lock)
Definition: tpi_openmp.c:631
int SCIPtpiGetThreadNum()
Definition: tpi_openmp.c:423
SCIP_RETCODE SCIPtpiReleaseLock(SCIP_LOCK *lock)
Definition: tpi_openmp.c:663
SCIP_RETCODE SCIPtpiInitCondition(SCIP_CONDITION **condition)
Definition: tpi_openmp.c:677
SCIP_RETCODE SCIPtpiInit(int nthreads, int queuesize, SCIP_Bool blockwhenfull)
Definition: tpi_openmp.c:596
#define SCIPompInitCondition(condition)
Definition: tpi_openmp.c:50
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_ERROR
Definition: type_retcode.h:43
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
enum SCIP_Submitstatus SCIP_SUBMITSTATUS
Definition: type_tpi.h:50
@ SCIP_SUBMIT_SUCCESS
Definition: type_tpi.h:48