static void *kts_worker(void *data) { kts_worker_t *w = (kts_worker_t*)data; for (;;) { int i, to_sync, n_slots; // update the task and slot information pthread_mutex_lock(&w->t->lock); while (w->i >= w->t->n_slots && !w->t->to_sync) pthread_cond_wait(&w->t->cv, &w->t->lock); to_sync = w->t->to_sync, n_slots = w->t->n_slots; pthread_mutex_unlock(&w->t->lock); // process the pending slot if there is any if (w->pending >= 0 && w->pending < n_slots) { process_slot(w->t, w->pending, w - w->t->w); w->pending = -1; } // process slots assigned to the current worker for (;;) { i = __sync_fetch_and_add(&w->i, w->t->n_threads); if (i >= n_slots) break; process_slot(w->t, i, w - w->t->w); } // steal slots from other workers for (;;) { int min = 0x7fffffff, min_i = 0; for (i = 0; i < w->t->n_threads; ++i) if (min > w->t->w[i].i) min = w->t->w[i].i, min_i = i; i = __sync_fetch_and_add(&w->t->w[min_i].i, w->t->n_threads); if (i >= n_slots) { w->pending = i; break; } else process_slot(w->t, i, w - w->t->w); } if (to_sync) break; } pthread_exit(0); }
/* Print cached content to stdout, generate the content if necessary. */ int cache_process(int size, const char *path, const char *key, int ttl, cache_fill_fn fn, void *cbdata) { unsigned long hash; int i; struct strbuf filename = STRBUF_INIT; struct strbuf lockname = STRBUF_INIT; struct cache_slot slot; int result; /* If the cache is disabled, just generate the content */ if (size <= 0) { fn(cbdata); return 0; } /* Verify input, calculate filenames */ if (!path) { cache_log("[cgit] Cache path not specified, caching is disabled\n"); fn(cbdata); return 0; } if (!key) key = ""; hash = hash_str(key) % size; strbuf_addstr(&filename, path); strbuf_ensure_end(&filename, '/'); for (i = 0; i < 8; i++) { strbuf_addf(&filename, "%x", (unsigned char)(hash & 0xf)); hash >>= 4; } strbuf_addbuf(&lockname, &filename); strbuf_addstr(&lockname, ".lock"); slot.fn = fn; slot.cbdata = cbdata; slot.ttl = ttl; slot.cache_name = filename.buf; slot.lock_name = lockname.buf; slot.key = key; slot.keylen = strlen(key); result = process_slot(&slot); strbuf_release(&filename); strbuf_release(&lockname); return result; }