2
* Copyright (c) 2011, Mark Heily <mark@heily.com>
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice unmodified, this list of conditions, and the following
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
#include "../private.h"
30
#include "pthread_workqueue.h"
32
#ifdef PROVIDE_LEGACY_XP_SUPPORT
34
static LIST_HEAD(, _pthread_workqueue) wqlist[WORKQ_NUM_PRIOQUEUE];
35
static pthread_rwlock_t wqlist_mtx;
40
pthread_rwlock_init(&wqlist_mtx, NULL);
45
manager_workqueue_create(struct _pthread_workqueue *workq)
47
pthread_rwlock_wrlock(&wqlist_mtx);
48
LIST_INSERT_HEAD(&wqlist[workq->queueprio], workq, wqlist_entry);
49
pthread_rwlock_unlock(&wqlist_mtx);
51
pthread_spin_init(&workq->mtx, PTHREAD_PROCESS_PRIVATE);
54
/* The caller must hold the wqlist_mtx. */
58
pthread_workqueue_t workq;
59
struct work *witem = NULL;
62
pthread_rwlock_rdlock(&wqlist_mtx);
63
for (i = 0; i < WORKQ_NUM_PRIOQUEUE; i++) {
64
LIST_FOREACH(workq, &wqlist[i], wqlist_entry) {
65
pthread_spin_lock(&workq->mtx);
67
if (STAILQ_EMPTY(&workq->item_listhead)) {
68
pthread_spin_unlock(&workq->mtx);
72
witem = STAILQ_FIRST(&workq->item_listhead);
74
STAILQ_REMOVE_HEAD(&workq->item_listhead, item_entry);
76
pthread_spin_unlock(&workq->mtx);
82
pthread_rwlock_unlock(&wqlist_mtx);
87
worker_main(LPVOID arg)
91
witem = wqlist_scan();
95
witem->func(witem->func_arg);
101
manager_workqueue_additem(struct _pthread_workqueue *workq, struct work *witem)
103
pthread_spin_lock(&workq->mtx);
104
STAILQ_INSERT_TAIL(&workq->item_listhead, witem, item_entry);
105
pthread_spin_unlock(&workq->mtx);
106
if (!QueueUserWorkItem(worker_main, NULL, WT_EXECUTELONGFUNCTION))
119
manager_workqueue_create(struct _pthread_workqueue *workq)
122
PTP_CALLBACK_ENVIRON callback;
125
pool = CreateThreadpool(NULL);
127
dbg_lasterror("CreateThreadpool()");
131
InitializeThreadpoolEnvironment(&workq->win_callback_env);
132
callback = &workq->win_callback_env;
133
SetThreadpoolCallbackPool(callback, pool);
135
switch(workq->queueprio){
136
case WORKQ_HIGH_PRIOQUEUE:
137
// weird but this seems the only valid solution !?
138
SetThreadpoolCallbackPriority(callback, TP_CALLBACK_PRIORITY_LOW);
140
case WORKQ_LOW_PRIOQUEUE:
142
SetThreadpoolCallbackPriority(callback, TP_CALLBACK_PRIORITY_HIGH);
145
SetThreadpoolCallbackPriority(callback, TP_CALLBACK_PRIORITY_NORMAL);
149
// we need a proper way to implement overcommitting on windows
150
if(workq->overcommit){
151
GetSystemInfo(&sysinfo);
152
SetThreadpoolThreadMaximum(pool, sysinfo.dwNumberOfProcessors * 2);
155
workq->win_thread_pool = pool;
159
worker_main( PTP_CALLBACK_INSTANCE instance, PVOID Parameter, PTP_WORK work )
161
struct work* witem = (struct work*)Parameter;
164
witem->func(witem->func_arg);
166
CloseThreadpoolWork(work);
170
manager_workqueue_additem(struct _pthread_workqueue *workq, struct work *witem)
172
PTP_WORK work = CreateThreadpoolWork(worker_main, witem, &workq->win_callback_env);
174
dbg_lasterror("CreateThreadpoolWork()");
177
SubmitThreadpoolWork(work);
180
// TODO: We need to cleanly close the environment and threadpools!
185
manager_peek(const char *key)
189
if (strcmp(key, "combined_idle") == 0) {
193
dbg_printf("invalid key: ", key);