ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libeio/etp.c
(Generate patch)

Comparing libeio/etp.c (file contents):
Revision 1.5 by root, Thu Jun 25 17:40:24 2015 UTC vs.
Revision 1.13 by root, Tue Aug 14 11:44:53 2018 UTC

1/* 1/*
2 * libetp implementation 2 * libetp implementation
3 * 3 *
4 * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libetp@schmorp.de> 4 * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2015 Marc Alexander Lehmann <libetp@schmorp.de>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without modifica- 7 * Redistribution and use in source and binary forms, with or without modifica-
8 * tion, are permitted provided that the following conditions are met: 8 * tion, are permitted provided that the following conditions are met:
9 * 9 *
35 * and other provisions required by the GPL. If you do not delete the 35 * and other provisions required by the GPL. If you do not delete the
36 * provisions above, a recipient may use your version of this file under 36 * provisions above, a recipient may use your version of this file under
37 * either the BSD or the GPL. 37 * either the BSD or the GPL.
38 */ 38 */
39 39
40#if HAVE_SYS_PRCTL_H
41# include <sys/prctl.h>
42#endif
43
40#ifndef ETP_API_DECL 44#ifndef ETP_API_DECL
41# define ETP_API_DECL static 45# define ETP_API_DECL static
42#endif 46#endif
43 47
44#ifndef ETP_PRI_MIN 48#ifndef ETP_PRI_MIN
50# define ETP_TYPE_QUIT 0 54# define ETP_TYPE_QUIT 0
51#endif 55#endif
52 56
53#ifndef ETP_TYPE_GROUP 57#ifndef ETP_TYPE_GROUP
54# define ETP_TYPE_GROUP 1 58# define ETP_TYPE_GROUP 1
59#endif
60
61#ifndef ETP_WANT_POLL
62# define ETP_WANT_POLL(pool) pool->want_poll_cb (pool->userdata)
63#endif
64#ifndef ETP_DONE_POLL
65# define ETP_DONE_POLL(pool) pool->done_poll_cb (pool->userdata)
55#endif 66#endif
56 67
57#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1) 68#define ETP_NUM_PRI (ETP_PRI_MAX - ETP_PRI_MIN + 1)
58 69
59#define ETP_TICKS ((1000000 + 1023) >> 10) 70#define ETP_TICKS ((1000000 + 1023) >> 10)
68etp_tvdiff (struct timeval *tv1, struct timeval *tv2) 79etp_tvdiff (struct timeval *tv1, struct timeval *tv2)
69{ 80{
70 return (tv2->tv_sec - tv1->tv_sec ) * ETP_TICKS 81 return (tv2->tv_sec - tv1->tv_sec ) * ETP_TICKS
71 + ((tv2->tv_usec - tv1->tv_usec) >> 10); 82 + ((tv2->tv_usec - tv1->tv_usec) >> 10);
72} 83}
73
74static unsigned int started, idle, wanted = 4;
75
76static void (*want_poll_cb) (void);
77static void (*done_poll_cb) (void);
78
79static unsigned int max_poll_time; /* reslock */
80static unsigned int max_poll_reqs; /* reslock */
81
82static unsigned int nreqs; /* reqlock */
83static unsigned int nready; /* reqlock */
84static unsigned int npending; /* reqlock */
85static unsigned int max_idle = 4; /* maximum number of threads that can idle indefinitely */
86static unsigned int idle_timeout = 10; /* number of seconds after which an idle threads exit */
87
88static xmutex_t wrklock;
89static xmutex_t reslock;
90static xmutex_t reqlock;
91static xcond_t reqwait;
92 84
93struct etp_tmpbuf 85struct etp_tmpbuf
94{ 86{
95 void *ptr; 87 void *ptr;
96 int len; 88 int len;
117{ 109{
118 ETP_REQ *qs[ETP_NUM_PRI], *qe[ETP_NUM_PRI]; /* qstart, qend */ 110 ETP_REQ *qs[ETP_NUM_PRI], *qe[ETP_NUM_PRI]; /* qstart, qend */
119 int size; 111 int size;
120} etp_reqq; 112} etp_reqq;
121 113
114typedef struct etp_pool *etp_pool;
115
116typedef struct etp_worker
117{
118 etp_pool pool;
119
120 struct etp_tmpbuf tmpbuf;
121
122 /* locked by pool->wrklock */
123 struct etp_worker *prev, *next;
124
125 xthread_t tid;
126
127#ifdef ETP_WORKER_COMMON
128 ETP_WORKER_COMMON
129#endif
130} etp_worker;
131
122struct etp_pool 132struct etp_pool
123{ 133{
134 void *userdata;
135
124 etp_reqq req_queue; 136 etp_reqq req_queue;
125 etp_reqq res_queue; 137 etp_reqq res_queue;
138
139 unsigned int started, idle, wanted;
140
141 unsigned int max_poll_time; /* pool->reslock */
142 unsigned int max_poll_reqs; /* pool->reslock */
143
144 unsigned int nreqs; /* pool->reqlock */
145 unsigned int nready; /* pool->reqlock */
146 unsigned int npending; /* pool->reqlock */
147 unsigned int max_idle; /* maximum number of threads that can pool->idle indefinitely */
148 unsigned int idle_timeout; /* number of seconds after which an pool->idle threads exit */
149
150 void (*want_poll_cb) (void *userdata);
151 void (*done_poll_cb) (void *userdata);
152
153 xmutex_t wrklock;
154 xmutex_t reslock;
155 xmutex_t reqlock;
156 xcond_t reqwait;
157
158 etp_worker wrk_first;
126}; 159};
127 160
128typedef struct etp_pool *etp_pool;
129
130typedef struct etp_worker
131{
132 etp_pool pool;
133
134 struct etp_tmpbuf tmpbuf;
135
136 /* locked by wrklock */
137 struct etp_worker *prev, *next;
138
139 xthread_t tid;
140
141#ifdef ETP_WORKER_COMMON
142 ETP_WORKER_COMMON
143#endif
144} etp_worker;
145
146static etp_worker wrk_first; /* NOT etp */
147
148#define ETP_WORKER_LOCK(wrk) X_LOCK (wrklock) 161#define ETP_WORKER_LOCK(wrk) X_LOCK (pool->wrklock)
149#define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (wrklock) 162#define ETP_WORKER_UNLOCK(wrk) X_UNLOCK (pool->wrklock)
150 163
151/* worker threads management */ 164/* worker threads management */
152 165
153static void 166static void
154etp_worker_clear (etp_worker *wrk) 167etp_worker_clear (etp_worker *wrk)
168 181
169ETP_API_DECL unsigned int 182ETP_API_DECL unsigned int
170etp_nreqs (etp_pool pool) 183etp_nreqs (etp_pool pool)
171{ 184{
172 int retval; 185 int retval;
173 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 186 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
174 retval = nreqs; 187 retval = pool->nreqs;
175 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 188 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
176 return retval; 189 return retval;
177} 190}
178 191
179ETP_API_DECL unsigned int 192ETP_API_DECL unsigned int
180etp_nready (etp_pool pool) 193etp_nready (etp_pool pool)
181{ 194{
182 unsigned int retval; 195 unsigned int retval;
183 196
184 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 197 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
185 retval = nready; 198 retval = pool->nready;
186 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 199 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
187 200
188 return retval; 201 return retval;
189} 202}
190 203
191ETP_API_DECL unsigned int 204ETP_API_DECL unsigned int
192etp_npending (etp_pool pool) 205etp_npending (etp_pool pool)
193{ 206{
194 unsigned int retval; 207 unsigned int retval;
195 208
196 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 209 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
197 retval = npending; 210 retval = pool->npending;
198 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 211 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
199 212
200 return retval; 213 return retval;
201} 214}
202 215
203ETP_API_DECL unsigned int 216ETP_API_DECL unsigned int
204etp_nthreads (etp_pool pool) 217etp_nthreads (etp_pool pool)
205{ 218{
206 unsigned int retval; 219 unsigned int retval;
207 220
208 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 221 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
209 retval = started; 222 retval = pool->started;
210 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 223 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
211 224
212 return retval; 225 return retval;
213} 226}
214 227
215static void ecb_noinline ecb_cold 228static void ecb_noinline ecb_cold
265 278
266 abort (); 279 abort ();
267} 280}
268 281
269ETP_API_DECL int ecb_cold 282ETP_API_DECL int ecb_cold
270etp_init (etp_pool pool, void (*want_poll)(void), void (*done_poll)(void)) 283etp_init (etp_pool pool, void *userdata, void (*want_poll)(void *userdata), void (*done_poll)(void *userdata))
271{ 284{
272 X_MUTEX_CREATE (wrklock); 285 X_MUTEX_CREATE (pool->wrklock);
273 X_MUTEX_CREATE (reslock); 286 X_MUTEX_CREATE (pool->reslock);
274 X_MUTEX_CREATE (reqlock); 287 X_MUTEX_CREATE (pool->reqlock);
275 X_COND_CREATE (reqwait); 288 X_COND_CREATE (pool->reqwait);
276 289
277 reqq_init (&pool->req_queue); 290 reqq_init (&pool->req_queue);
278 reqq_init (&pool->res_queue); 291 reqq_init (&pool->res_queue);
279 292
280 wrk_first.next = 293 pool->wrk_first.next =
281 wrk_first.prev = &wrk_first; 294 pool->wrk_first.prev = &pool->wrk_first;
282 295
283 started = 0; 296 pool->started = 0;
284 idle = 0; 297 pool->idle = 0;
285 nreqs = 0; 298 pool->nreqs = 0;
286 nready = 0; 299 pool->nready = 0;
287 npending = 0; 300 pool->npending = 0;
301 pool->wanted = 4;
288 302
303 pool->max_idle = 4; /* maximum number of threads that can pool->idle indefinitely */
304 pool->idle_timeout = 10; /* number of seconds after which an pool->idle threads exit */
305
306 pool->userdata = userdata;
289 want_poll_cb = want_poll; 307 pool->want_poll_cb = want_poll;
290 done_poll_cb = done_poll; 308 pool->done_poll_cb = done_poll;
291 309
292 return 0; 310 return 0;
293} 311}
294 312
295static void ecb_noinline ecb_cold 313static void ecb_noinline ecb_cold
323 341
324 for (;;) 342 for (;;)
325 { 343 {
326 ts.tv_sec = 0; 344 ts.tv_sec = 0;
327 345
328 X_LOCK (reqlock); 346 X_LOCK (pool->reqlock);
329 347
330 for (;;) 348 for (;;)
331 { 349 {
332 req = reqq_shift (&pool->req_queue); 350 req = reqq_shift (&pool->req_queue);
333 351
334 if (req) 352 if (ecb_expect_true (req))
335 break; 353 break;
336 354
337 if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */ 355 if (ts.tv_sec == 1) /* no request, but timeout detected, let's quit */
338 { 356 {
339 X_UNLOCK (reqlock); 357 X_UNLOCK (pool->reqlock);
340 X_LOCK (wrklock); 358 X_LOCK (pool->wrklock);
341 --started; 359 --pool->started;
342 X_UNLOCK (wrklock); 360 X_UNLOCK (pool->wrklock);
343 goto quit; 361 goto quit;
344 } 362 }
345 363
346 ++idle; 364 ++pool->idle;
347 365
348 if (idle <= max_idle) 366 if (pool->idle <= pool->max_idle)
349 /* we are allowed to idle, so do so without any timeout */ 367 /* we are allowed to pool->idle, so do so without any timeout */
350 X_COND_WAIT (reqwait, reqlock); 368 X_COND_WAIT (pool->reqwait, pool->reqlock);
351 else 369 else
352 { 370 {
353 /* initialise timeout once */ 371 /* initialise timeout once */
354 if (!ts.tv_sec) 372 if (!ts.tv_sec)
355 ts.tv_sec = time (0) + idle_timeout; 373 ts.tv_sec = time (0) + pool->idle_timeout;
356 374
357 if (X_COND_TIMEDWAIT (reqwait, reqlock, ts) == ETIMEDOUT) 375 if (X_COND_TIMEDWAIT (pool->reqwait, pool->reqlock, ts) == ETIMEDOUT)
358 ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */ 376 ts.tv_sec = 1; /* assuming this is not a value computed above.,.. */
359 } 377 }
360 378
361 --idle; 379 --pool->idle;
362 } 380 }
363 381
364 --nready; 382 --pool->nready;
365 383
366 X_UNLOCK (reqlock); 384 X_UNLOCK (pool->reqlock);
367 385
368 if (req->type == ETP_TYPE_QUIT) 386 if (ecb_expect_false (req->type == ETP_TYPE_QUIT))
369 goto quit; 387 goto quit;
370 388
371 ETP_EXECUTE (self, req); 389 ETP_EXECUTE (self, req);
372 390
373 X_LOCK (reslock); 391 X_LOCK (pool->reslock);
374 392
375 ++npending; 393 ++pool->npending;
376 394
377 if (!reqq_push (&pool->res_queue, req) && want_poll_cb) 395 if (!reqq_push (&pool->res_queue, req))
378 want_poll_cb (); 396 ETP_WANT_POLL (pool);
379 397
380 etp_worker_clear (self); 398 etp_worker_clear (self);
381 399
382 X_UNLOCK (reslock); 400 X_UNLOCK (pool->reslock);
383 } 401 }
384 402
385quit: 403quit:
386 free (req); 404 free (req);
387 405
388 X_LOCK (wrklock); 406 X_LOCK (pool->wrklock);
389 etp_worker_free (self); 407 etp_worker_free (self);
390 X_UNLOCK (wrklock); 408 X_UNLOCK (pool->wrklock);
391 409
392 return 0; 410 return 0;
393} 411}
394 412
395static void ecb_cold 413static void ecb_cold
400 /*TODO*/ 418 /*TODO*/
401 assert (("unable to allocate worker thread data", wrk)); 419 assert (("unable to allocate worker thread data", wrk));
402 420
403 wrk->pool = pool; 421 wrk->pool = pool;
404 422
405 X_LOCK (wrklock); 423 X_LOCK (pool->wrklock);
406 424
407 if (xthread_create (&wrk->tid, etp_proc, (void *)wrk)) 425 if (xthread_create (&wrk->tid, etp_proc, (void *)wrk))
408 { 426 {
409 wrk->prev = &wrk_first; 427 wrk->prev = &pool->wrk_first;
410 wrk->next = wrk_first.next; 428 wrk->next = pool->wrk_first.next;
411 wrk_first.next->prev = wrk; 429 pool->wrk_first.next->prev = wrk;
412 wrk_first.next = wrk; 430 pool->wrk_first.next = wrk;
413 ++started; 431 ++pool->started;
414 } 432 }
415 else 433 else
416 free (wrk); 434 free (wrk);
417 435
418 X_UNLOCK (wrklock); 436 X_UNLOCK (pool->wrklock);
419} 437}
420 438
421static void 439static void
422etp_maybe_start_thread (etp_pool pool) 440etp_maybe_start_thread (etp_pool pool)
423{ 441{
424 if (ecb_expect_true (etp_nthreads (pool) >= wanted)) 442 if (ecb_expect_true (etp_nthreads (pool) >= pool->wanted))
425 return; 443 return;
426 444
427 /* todo: maybe use idle here, but might be less exact */ 445 /* todo: maybe use pool->idle here, but might be less exact */
428 if (ecb_expect_true (0 <= (int)etp_nthreads (pool) + (int)etp_npending (pool) - (int)etp_nreqs (pool))) 446 if (ecb_expect_true (0 <= (int)etp_nthreads (pool) + (int)etp_npending (pool) - (int)etp_nreqs (pool)))
429 return; 447 return;
430 448
431 etp_start_thread (pool); 449 etp_start_thread (pool);
432} 450}
437 ETP_REQ *req = calloc (1, sizeof (ETP_REQ)); /* will be freed by worker */ 455 ETP_REQ *req = calloc (1, sizeof (ETP_REQ)); /* will be freed by worker */
438 456
439 req->type = ETP_TYPE_QUIT; 457 req->type = ETP_TYPE_QUIT;
440 req->pri = ETP_PRI_MAX - ETP_PRI_MIN; 458 req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
441 459
442 X_LOCK (reqlock); 460 X_LOCK (pool->reqlock);
443 reqq_push (&pool->req_queue, req); 461 reqq_push (&pool->req_queue, req);
444 X_COND_SIGNAL (reqwait); 462 X_COND_SIGNAL (pool->reqwait);
445 X_UNLOCK (reqlock); 463 X_UNLOCK (pool->reqlock);
446 464
447 X_LOCK (wrklock); 465 X_LOCK (pool->wrklock);
448 --started; 466 --pool->started;
449 X_UNLOCK (wrklock); 467 X_UNLOCK (pool->wrklock);
450} 468}
451 469
452ETP_API_DECL int 470ETP_API_DECL int
453etp_poll (etp_pool pool) 471etp_poll (etp_pool pool)
454{ 472{
455 unsigned int maxreqs; 473 unsigned int maxreqs;
456 unsigned int maxtime; 474 unsigned int maxtime;
457 struct timeval tv_start, tv_now; 475 struct timeval tv_start, tv_now;
458 476
459 X_LOCK (reslock); 477 X_LOCK (pool->reslock);
460 maxreqs = max_poll_reqs; 478 maxreqs = pool->max_poll_reqs;
461 maxtime = max_poll_time; 479 maxtime = pool->max_poll_time;
462 X_UNLOCK (reslock); 480 X_UNLOCK (pool->reslock);
463 481
464 if (maxtime) 482 if (maxtime)
465 gettimeofday (&tv_start, 0); 483 gettimeofday (&tv_start, 0);
466 484
467 for (;;) 485 for (;;)
468 { 486 {
469 ETP_REQ *req; 487 ETP_REQ *req;
470 488
471 etp_maybe_start_thread (pool); 489 etp_maybe_start_thread (pool);
472 490
473 X_LOCK (reslock); 491 X_LOCK (pool->reslock);
474 req = reqq_shift (&pool->res_queue); 492 req = reqq_shift (&pool->res_queue);
475 493
476 if (req) 494 if (ecb_expect_true (req))
477 { 495 {
478 --npending; 496 --pool->npending;
479 497
480 if (!pool->res_queue.size && done_poll_cb) 498 if (!pool->res_queue.size)
481 done_poll_cb (); 499 ETP_DONE_POLL (pool);
482 } 500 }
483 501
484 X_UNLOCK (reslock); 502 X_UNLOCK (pool->reslock);
485 503
486 if (!req) 504 if (ecb_expect_false (!req))
487 return 0; 505 return 0;
488 506
489 X_LOCK (reqlock); 507 X_LOCK (pool->reqlock);
490 --nreqs; 508 --pool->nreqs;
491 X_UNLOCK (reqlock); 509 X_UNLOCK (pool->reqlock);
492 510
493 if (ecb_expect_false (req->type == ETP_TYPE_GROUP && req->size)) 511 if (ecb_expect_false (req->type == ETP_TYPE_GROUP && req->size))
494 { 512 {
495 req->flags |= ETP_FLAG_DELAYED; /* mark request as delayed */ 513 req->flags |= ETP_FLAG_DELAYED; /* mark request as delayed */
496 continue; 514 continue;
545 if (ecb_expect_false (req->pri > ETP_PRI_MAX - ETP_PRI_MIN)) req->pri = ETP_PRI_MAX - ETP_PRI_MIN; 563 if (ecb_expect_false (req->pri > ETP_PRI_MAX - ETP_PRI_MIN)) req->pri = ETP_PRI_MAX - ETP_PRI_MIN;
546 564
547 if (ecb_expect_false (req->type == ETP_TYPE_GROUP)) 565 if (ecb_expect_false (req->type == ETP_TYPE_GROUP))
548 { 566 {
549 /* I hope this is worth it :/ */ 567 /* I hope this is worth it :/ */
550 X_LOCK (reqlock); 568 X_LOCK (pool->reqlock);
551 ++nreqs; 569 ++pool->nreqs;
552 X_UNLOCK (reqlock); 570 X_UNLOCK (pool->reqlock);
553 571
554 X_LOCK (reslock); 572 X_LOCK (pool->reslock);
555 573
556 ++npending; 574 ++pool->npending;
557 575
558 if (!reqq_push (&pool->res_queue, req) && want_poll_cb) 576 if (!reqq_push (&pool->res_queue, req))
559 want_poll_cb (); 577 ETP_WANT_POLL (pool);
560 578
561 X_UNLOCK (reslock); 579 X_UNLOCK (pool->reslock);
562 } 580 }
563 else 581 else
564 { 582 {
565 X_LOCK (reqlock); 583 X_LOCK (pool->reqlock);
566 ++nreqs; 584 ++pool->nreqs;
567 ++nready; 585 ++pool->nready;
568 reqq_push (&pool->req_queue, req); 586 reqq_push (&pool->req_queue, req);
569 X_COND_SIGNAL (reqwait); 587 X_COND_SIGNAL (pool->reqwait);
570 X_UNLOCK (reqlock); 588 X_UNLOCK (pool->reqlock);
571 589
572 etp_maybe_start_thread (pool); 590 etp_maybe_start_thread (pool);
573 } 591 }
574} 592}
575 593
576ETP_API_DECL void ecb_cold 594ETP_API_DECL void ecb_cold
577etp_set_max_poll_time (etp_pool pool, double nseconds) 595etp_set_max_poll_time (etp_pool pool, double seconds)
578{ 596{
579 if (WORDACCESS_UNSAFE) X_LOCK (reslock); 597 if (WORDACCESS_UNSAFE) X_LOCK (pool->reslock);
580 max_poll_time = nseconds * ETP_TICKS; 598 pool->max_poll_time = seconds * ETP_TICKS;
581 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock); 599 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reslock);
582} 600}
583 601
584ETP_API_DECL void ecb_cold 602ETP_API_DECL void ecb_cold
585etp_set_max_poll_reqs (etp_pool pool, unsigned int maxreqs) 603etp_set_max_poll_reqs (etp_pool pool, unsigned int maxreqs)
586{ 604{
587 if (WORDACCESS_UNSAFE) X_LOCK (reslock); 605 if (WORDACCESS_UNSAFE) X_LOCK (pool->reslock);
588 max_poll_reqs = maxreqs; 606 pool->max_poll_reqs = maxreqs;
589 if (WORDACCESS_UNSAFE) X_UNLOCK (reslock); 607 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reslock);
590} 608}
591 609
592ETP_API_DECL void ecb_cold 610ETP_API_DECL void ecb_cold
593etp_set_max_idle (etp_pool pool, unsigned int nthreads) 611etp_set_max_idle (etp_pool pool, unsigned int threads)
594{ 612{
595 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 613 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
596 max_idle = nthreads; 614 pool->max_idle = threads;
597 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 615 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
598} 616}
599 617
600ETP_API_DECL void ecb_cold 618ETP_API_DECL void ecb_cold
601etp_set_idle_timeout (etp_pool pool, unsigned int seconds) 619etp_set_idle_timeout (etp_pool pool, unsigned int seconds)
602{ 620{
603 if (WORDACCESS_UNSAFE) X_LOCK (reqlock); 621 if (WORDACCESS_UNSAFE) X_LOCK (pool->reqlock);
604 idle_timeout = seconds; 622 pool->idle_timeout = seconds;
605 if (WORDACCESS_UNSAFE) X_UNLOCK (reqlock); 623 if (WORDACCESS_UNSAFE) X_UNLOCK (pool->reqlock);
606} 624}
607 625
608ETP_API_DECL void ecb_cold 626ETP_API_DECL void ecb_cold
609etp_set_min_parallel (etp_pool pool, unsigned int nthreads) 627etp_set_min_parallel (etp_pool pool, unsigned int threads)
610{ 628{
611 if (wanted < nthreads) 629 if (pool->wanted < threads)
612 wanted = nthreads; 630 pool->wanted = threads;
613} 631}
614 632
615ETP_API_DECL void ecb_cold 633ETP_API_DECL void ecb_cold
616etp_set_max_parallel (etp_pool pool, unsigned int nthreads) 634etp_set_max_parallel (etp_pool pool, unsigned int threads)
617{ 635{
618 if (wanted > nthreads) 636 if (pool->wanted > threads)
619 wanted = nthreads; 637 pool->wanted = threads;
620 638
621 while (started > wanted) 639 while (pool->started > pool->wanted)
622 etp_end_thread (pool); 640 etp_end_thread (pool);
623} 641}
624 642

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines