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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines