Beispiel #1
0
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

}
Beispiel #2
0
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;
}
Beispiel #3
0
/**
 * 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);
}
Beispiel #4
0
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;
}
Beispiel #6
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
void echoClient_stop(echo_client_pt client) {
    apr_status_t status;
    client->running = false;
    apr_thread_join(&status, client->sender);
}
Beispiel #10
0
int poll_worker_stop(poll_worker_t *worker) {
    apr_status_t status = 0;
    apr_thread_join(&status, worker->th_poll);
    return 0;
}