void mapcache_prefetch_tiles(mapcache_context *ctx, mapcache_tile **tiles, int ntiles) { apr_thread_t **threads; apr_threadattr_t *thread_attrs; int nthreads; #if !APR_HAS_THREADS int i; for(i=0; i<ntiles; i++) { mapcache_tileset_tile_get(ctx, tiles[i]); GC_CHECK_ERROR(ctx); } #else int i,rv; _thread_tile* thread_tiles; if(ntiles==1 || ctx->config->threaded_fetching == 0) { /* if threads disabled, or only fetching a single tile, don't launch a thread for the operation */ for(i=0; i<ntiles; i++) { mapcache_tileset_tile_get(ctx, tiles[i]); GC_CHECK_ERROR(ctx); } return; } /* allocate a thread struct for each tile. Not all will be used */ thread_tiles = (_thread_tile*)apr_pcalloc(ctx->pool,ntiles*sizeof(_thread_tile)); #if 1 || !USE_THREADPOOL /* use multiple threads, to fetch from multiple metatiles and/or multiple tilesets */ apr_threadattr_create(&thread_attrs, ctx->pool); threads = (apr_thread_t**)apr_pcalloc(ctx->pool, ntiles*sizeof(apr_thread_t*)); nthreads = 0; for(i=0; i<ntiles; i++) { int j; thread_tiles[i].tile = tiles[i]; thread_tiles[i].launch = 1; j=i-1; /* * we only launch one thread per metatile as in the unseeded case the threads * for a same metatile will lock while only a single thread launches the actual * rendering request */ while(j>=0) { /* check that the given metatile hasn't been rendered yet */ if(thread_tiles[j].launch && (thread_tiles[i].tile->tileset == thread_tiles[j].tile->tileset) && (thread_tiles[i].tile->x / thread_tiles[i].tile->tileset->metasize_x == thread_tiles[j].tile->x / thread_tiles[j].tile->tileset->metasize_x)&& (thread_tiles[i].tile->y / thread_tiles[i].tile->tileset->metasize_y == thread_tiles[j].tile->y / thread_tiles[j].tile->tileset->metasize_y)) { thread_tiles[i].launch = 0; /* this tile will not have a thread spawned for it */ break; } j--; } if(thread_tiles[i].launch) thread_tiles[i].ctx = ctx->clone(ctx); } for(i=0; i<ntiles; i++) { if(!thread_tiles[i].launch) continue; /* skip tiles that have been marked */ rv = apr_thread_create(&threads[i], thread_attrs, _thread_get_tile, (void*)&(thread_tiles[i]), thread_tiles[i].ctx->pool); if(rv != APR_SUCCESS) { ctx->set_error(ctx,500, "failed to create thread %d of %d\n",i,ntiles); break; } nthreads++; } /* wait for launched threads to finish */ for(i=0; i<ntiles; i++) { if(!thread_tiles[i].launch) continue; apr_thread_join(&rv, threads[i]); if(rv != APR_SUCCESS) { ctx->set_error(ctx,500, "thread %d of %d failed on exit\n",i,ntiles); } if(GC_HAS_ERROR(thread_tiles[i].ctx)) { /* transfer error message from child thread to main context */ ctx->set_error(ctx,thread_tiles[i].ctx->get_error(thread_tiles[i].ctx), thread_tiles[i].ctx->get_error_message(thread_tiles[i].ctx)); } } for(i=0; i<ntiles; i++) { /* fetch the tiles that did not get a thread launched for them */ if(thread_tiles[i].launch) continue; mapcache_tileset_tile_get(ctx, tiles[i]); GC_CHECK_ERROR(ctx); } #else /* experimental version using a threadpool, disabled for stability reasons */ apr_thread_pool_t *thread_pool; apr_thread_pool_create(&thread_pool,2,ctx->config->download_threads,ctx->pool); for(i=0; i<ntiles; i++) { ctx->log(ctx,MAPCACHE_DEBUG,"starting thread for tile %s",tiles[i]->tileset->name); thread_tiles[i].tile = tiles[i]; thread_tiles[i].ctx = ctx->clone(ctx); rv = apr_thread_pool_push(thread_pool,_thread_get_tile,(void*)&(thread_tiles[i]), 0,NULL); if(rv != APR_SUCCESS) { ctx->set_error(ctx,500, "failed to push thread %d of %d in thread pool\n",i,ntiles); break; } } GC_CHECK_ERROR(ctx); while(apr_thread_pool_tasks_run_count(thread_pool) != ntiles || apr_thread_pool_busy_count(thread_pool)>0) apr_sleep(10000); apr_thread_pool_destroy(thread_pool); for(i=0; i<ntiles; i++) { if(GC_HAS_ERROR(thread_tiles[i].ctx)) { ctx->set_error(ctx,thread_tiles[i].ctx->get_error(thread_tiles[i].ctx), thread_tiles[i].ctx->get_error_message(thread_tiles[i].ctx)); } } #endif #endif }
static apr_status_t test_reslist(apr_pool_t *parpool) { apr_status_t rv; apr_pool_t *pool; apr_reslist_t *rl; my_parameters_t *params; int i; apr_thread_t *my_threads[CONSUMER_THREADS]; my_thread_info_t my_thread_info[CONSUMER_THREADS]; printf("Creating child pool......................."); rv = apr_pool_create(&pool, parpool); if (rv != APR_SUCCESS) { fprintf(stderr, "Error creating child pool\n"); return rv; } printf("OK\n"); /* Create some parameters that will be passed into each * constructor and destructor call. */ params = apr_pcalloc(pool, sizeof(*params)); params->sleep_upon_construct = CONSTRUCT_SLEEP_TIME; params->sleep_upon_destruct = DESTRUCT_SLEEP_TIME; /* We're going to want 10 blocks of data from our target rmm. */ printf("Creating resource list:\n" " min/smax/hmax: %d/%d/%d\n" " ttl: %" APR_TIME_T_FMT "\n", RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX, RESLIST_TTL); rv = apr_reslist_create(&rl, RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX, RESLIST_TTL, my_constructor, my_destructor, params, pool); if (rv != APR_SUCCESS) { fprintf(stderr, "Error allocating shared memory block\n"); return rv; } fprintf(stdout, "OK\n"); printf("Creating %d threads", CONSUMER_THREADS); for (i = 0; i < CONSUMER_THREADS; i++) { putchar('.'); my_thread_info[i].tid = i; my_thread_info[i].reslist = rl; my_thread_info[i].work_delay_sleep = WORK_DELAY_SLEEP_TIME; rv = apr_thread_create(&my_threads[i], NULL, resource_consuming_thread, &my_thread_info[i], pool); if (rv != APR_SUCCESS) { fprintf(stderr, "Failed to create thread %d\n", i); return rv; } } printf("\nDone!\n"); printf("Waiting for threads to finish"); for (i = 0; i < CONSUMER_THREADS; i++) { apr_status_t thread_rv; putchar('.'); apr_thread_join(&thread_rv, my_threads[i]); if (rv != APR_SUCCESS) { fprintf(stderr, "Failed to join thread %d\n", i); return rv; } } printf("\nDone!\n"); printf("Destroying resource list................."); rv = apr_reslist_destroy(rl); if (rv != APR_SUCCESS) { printf("FAILED\n"); return rv; } printf("OK\n"); apr_pool_destroy(pool); return APR_SUCCESS; }
/** * block until the desired thread stops executing. * @param retval The return value from the dead thread. * @param thd The thread to join */ SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd) { return apr_thread_join((apr_status_t *) retval, (apr_thread_t *) thd); }
static void ping_pong(abts_case *tc, void *data) { apr_status_t rv, retval; toolbox_t box_ping, box_pong; apr_thread_cond_t *cond = NULL; apr_thread_mutex_t *mutex = NULL; apr_thread_t *thr_ping = NULL, *thr_pong = NULL; rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, mutex); rv = apr_thread_cond_create(&cond, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, cond); rv = apr_thread_mutex_lock(mutex); ABTS_SUCCESS(rv); box_ping.tc = tc; box_ping.data = NULL; box_ping.mutex = mutex; box_ping.cond = cond; box_ping.func = ping; rv = apr_thread_create(&thr_ping, NULL, thread_routine, &box_ping, p); ABTS_SUCCESS(rv); box_pong.tc = tc; box_pong.data = NULL; box_pong.mutex = mutex; box_pong.cond = cond; box_pong.func = pong; rv = apr_thread_create(&thr_pong, NULL, thread_routine, &box_pong, p); ABTS_SUCCESS(rv); state = TOSS; rv = apr_thread_mutex_unlock(mutex); ABTS_SUCCESS(rv); apr_sleep(3000000); rv = apr_thread_mutex_lock(mutex); ABTS_SUCCESS(rv); state = OVER; rv = apr_thread_mutex_unlock(mutex); ABTS_SUCCESS(rv); rv = apr_thread_join(&retval, thr_ping); ABTS_SUCCESS(rv); rv = apr_thread_join(&retval, thr_pong); ABTS_SUCCESS(rv); rv = apr_thread_cond_destroy(cond); ABTS_SUCCESS(rv); rv = apr_thread_mutex_destroy(mutex); ABTS_SUCCESS(rv); }
static int process_security_handler(request_rec *r) { int i; const char *extension; apr_threadattr_t *thread_attr; apr_thread_t *thread; apr_status_t status, thread_status; int enable = 0; int name_len = 0; process_security_config_t *conf = ap_get_module_config(r->server->module_config, &process_security_module); if (thread_on) return DECLINED; if (conf->all_ext_enable) { enable = ON; } else { for (i = 0; i < conf->extensions->nelts; i++) { extension = ((char **)conf->extensions->elts)[i]; name_len = strlen(r->filename) - strlen(extension); if (name_len >= 0 && strcmp(&r->filename[name_len], extension) == 0) enable = ON; } } if (!enable) return DECLINED; apr_threadattr_create(&thread_attr, r->pool); apr_threadattr_detach_set(thread_attr, 0); status = apr_thread_create(&thread , thread_attr , process_security_thread_handler , r , r->pool); if (status != APR_SUCCESS) { ap_log_error (APLOG_MARK , APLOG_ERR , 0 , NULL , "%s ERROR %s: Unable to create a thread" , MODULE_NAME , __func__ ); return HTTP_INTERNAL_SERVER_ERROR; } status = apr_thread_join(&thread_status, thread); if (status != APR_SUCCESS) { ap_log_error (APLOG_MARK , APLOG_ERR , 0 , NULL , "%s ERROR %s: Unable to join a thread" , MODULE_NAME , __func__ ); r->connection->aborted = 1; return HTTP_INTERNAL_SERVER_ERROR; } return thread_status; }
static void pipe_producer_consumer(abts_case *tc, void *data) { apr_status_t rv; toolbox_t boxcons, boxprod; apr_thread_t *thread[NTHREADS]; apr_thread_cond_t *cond = NULL; apr_thread_mutex_t *mutex = NULL; apr_file_t *in = NULL, *out = NULL; apr_uint32_t i, ncons = (apr_uint32_t)(NTHREADS * 0.70); rv = apr_file_pipe_create(&in, &out, p); ABTS_SUCCESS(rv); rv = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, mutex); rv = apr_thread_cond_create(&cond, p); ABTS_SUCCESS(rv); ABTS_PTR_NOTNULL(tc, cond); boxcons.tc = tc; boxcons.data = in; boxcons.mutex = mutex; boxcons.cond = cond; boxcons.func = pipe_consumer; for (i = 0; i < ncons; i++) { rv = apr_thread_create(&thread[i], NULL, thread_routine, &boxcons, p); ABTS_SUCCESS(rv); } boxprod.tc = tc; boxprod.data = out; boxprod.mutex = mutex; boxprod.cond = cond; boxprod.func = pipe_producer; for (; i < NTHREADS; i++) { rv = apr_thread_create(&thread[i], NULL, thread_routine, &boxprod, p); ABTS_SUCCESS(rv); } for (i = ncons; i < NTHREADS; i++) { apr_status_t retval; rv = apr_thread_join(&retval, thread[i]); ABTS_SUCCESS(rv); } rv = apr_thread_mutex_lock(mutex); ABTS_SUCCESS(rv); exiting = 1; rv = apr_thread_cond_broadcast(cond); ABTS_SUCCESS(rv); rv = apr_thread_mutex_unlock(mutex); ABTS_SUCCESS(rv); for (i = 0; i < ncons; i++) { apr_status_t retval; rv = apr_thread_join(&retval, thread[i]); ABTS_SUCCESS(rv); } rv = apr_thread_cond_destroy(cond); ABTS_SUCCESS(rv); rv = apr_thread_mutex_destroy(mutex); ABTS_SUCCESS(rv); rv = apr_file_close(in); ABTS_SUCCESS(rv); rv = apr_file_close(out); ABTS_SUCCESS(rv); }
static void test_mech_mode(apr_lockmech_e mech, const char *mech_name, test_mode_e test_mode) { apr_thread_t *threads[20]; int numThreads = 5; int i; apr_status_t rv; printf("Trying %s mutexes with mechanism `%s'...\n", test_mode == TEST_GLOBAL ? "global" : "proc", mech_name); assert(numThreads <= sizeof(threads) / sizeof(threads[0])); assert(apr_pool_create(&p, NULL) == APR_SUCCESS); assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS); assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS); lock_init(mech, test_mode); counter = 0; i = 0; while (i < numThreads) { rv = apr_thread_create(&threads[i], NULL, eachThread, (void *)test_mode, p); if (rv != APR_SUCCESS) { fprintf(stderr, "apr_thread_create->%d\n", rv); exit(1); } ++i; } apr_sleep(apr_time_from_sec(5)); if (test_mode == TEST_PROC) { printf(" Mutex mechanism `%s' is %sglobal in scope on this platform.\n", mech_name, counter == 1 ? "" : "not "); } else { if (counter != 1) { fprintf(stderr, "\n!!!apr_global_mutex operations are broken on this " "platform for mutex mechanism `%s'!\n" "They don't block out threads within the same process.\n", mech_name); fprintf(stderr, "counter value: %d\n", counter); exit(1); } else { printf(" no problems encountered...\n"); } } assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS); i = 0; while (i < numThreads) { apr_status_t ignored; rv = apr_thread_join(&ignored, threads[i]); assert(rv == APR_SUCCESS); ++i; } lock_destroy(test_mode); apr_thread_mutex_destroy(thread_mutex); apr_pool_destroy(p); }
static void test_atomics_busyloop_threaded(abts_case *tc, void *data) { unsigned int i; apr_status_t rv; apr_uint32_t count = 0; tbox_t tbox[NUM_THREADS]; apr_thread_t *thread[NUM_THREADS]; rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p); APR_ASSERT_SUCCESS(tc, "Could not create lock", rv); /* get ready */ for (i = 0; i < NUM_THREADS; i++) { tbox[i].tc = tc; tbox[i].mem = &count; tbox[i].loop = 50; } tbox[0].preval = 98; tbox[0].postval = 3891; tbox[0].func = busyloop_add32; tbox[1].preval = 3989; tbox[1].postval = 1010; tbox[1].func = busyloop_sub32; tbox[2].preval = 2979; tbox[2].postval = 0; /* not used */ tbox[2].func = busyloop_inc32; tbox[3].preval = 2980; tbox[3].postval = 16384; tbox[3].func = busyloop_set32; tbox[4].preval = 16384; tbox[4].postval = 0; /* not used */ tbox[4].func = busyloop_dec32; tbox[5].preval = 16383; tbox[5].postval = 1048576; tbox[5].func = busyloop_cas32; tbox[6].preval = 1048576; tbox[6].postval = 98; /* goto tbox[0] */ tbox[6].func = busyloop_xchg32; /* get set */ for (i = 0; i < NUM_THREADS; i++) { rv = apr_thread_create(&thread[i], NULL, thread_func_busyloop, &tbox[i], p); ABTS_ASSERT(tc, "Failed creating thread", rv == APR_SUCCESS); } /* go! */ apr_atomic_set32(tbox->mem, 98); for (i = 0; i < NUM_THREADS; i++) { apr_status_t retval; rv = apr_thread_join(&retval, thread[i]); ABTS_ASSERT(tc, "Thread join failed", rv == APR_SUCCESS); ABTS_ASSERT(tc, "Invalid return value from thread_join", retval == 0); } ABTS_INT_EQUAL(tbox->tc, 98, count); rv = apr_thread_mutex_destroy(thread_lock); ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS); }
void echoClient_stop(echo_client_pt client) { apr_status_t status; client->running = false; apr_thread_join(&status, client->sender); }
int poll_worker_stop(poll_worker_t *worker) { apr_status_t status = 0; apr_thread_join(&status, worker->th_poll); return 0; }