static void *
outer_thread (void *closure)
{
  pthread_t *threads = xcalloc (sizeof (*threads), inner_thread_count);
  while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
    {
      pthread_barrier_t barrier;
      xpthread_barrier_init (&barrier, NULL, inner_thread_count + 1);
      for (int i = 0; i < inner_thread_count; ++i)
        {
          void *(*func) (void *);
          if ((i  % 2) == 0)
            func = malloc_first_thread;
          else
            func = wait_first_thread;
          threads[i] = xpthread_create (NULL, func, &barrier);
        }
      xpthread_barrier_wait (&barrier);
      for (int i = 0; i < inner_thread_count; ++i)
        xpthread_join (threads[i]);
      xpthread_barrier_destroy (&barrier);
    }

  free (threads);

  return NULL;
}
Exemple #2
0
/*
 * The accept thread's job is easy.
 * Accept a new connection and pass it off to a work thread.  Repeat.
 */
void *
accept_thread(void *arg)
{
  config_t *config = (config_t *) arg;
  int s;

  struct sockaddr_un sa;
  socklen_t salen = sizeof(sa);

  mlog(LOG_DEBUG2, "%s: tid=%lu", __func__, (unsigned long) pthread_self());

  for (;;) {
    s = accept(config->s, (struct sockaddr *) &sa, &salen);
    if (s == -1) {
      mlog(LOG_ERR, "%s: plugin accept: %s", __func__, strerror(errno));
      /* not much else we can do */
      continue;
    }
    mlog(LOG_DEBUG, "%s: plugin accept fd=%d", __func__, s);

    /*
     * start a work thread (1:1 model)
     */
    {
      pthread_t tid;
      config_t *inst;

      inst = xmalloc(sizeof(*config));
      (void) memcpy(inst, config, sizeof(*config));
      inst->s = s;
      xpthread_create(&tid, &attr_detached, work_thread, inst);
    }

  } /* for (;;) */
}
Exemple #3
0
int
do_test (void)
{
  xpthread_rwlockattr_init (&mylock_attr);
  xpthread_rwlockattr_setkind_np (&mylock_attr,
				  PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
  xpthread_rwlock_init (&mylock, &mylock_attr);

  for (int n = 0; n < LOOPS; n++)
    {
      pthread_t tids[NTHREADS];
      do_exit = 0;
      for (int i = 0; i < NTHREADS; i++)
	tids[i] = xpthread_create (NULL, run_loop, NULL);
      /* Let the threads run for some time.  */
      sleep (1);
      printf ("Exiting...");
      fflush (stdout);
      do_exit = 1;
      for (int i = 0; i < NTHREADS; i++)
	xpthread_join (tids[i]);
      printf ("done.\n");
    }
  pthread_rwlock_destroy (&mylock);
  pthread_rwlockattr_destroy (&mylock_attr);
  return 0;
}
Exemple #4
0
static void benchmark(void)
{
	int i;
	long sum = 0;
	long min_ms = LONG_MAX, max_ms = 0, avg_ms;
	pthread_t *tid;
	struct benchmark_thread_data *data;

#ifdef CHUNKD_BENCHMARK
	stc_init();
#endif

	tid = xmalloc(sizeof(tid[0]) * threads);
	data = xmalloc(sizeof(data[0]) * threads);

	for (i = 0; i < threads; i++) {
		data[i].id = i;
		xpthread_create(&tid[i], NULL, benchmark_thread, &data[i]);
	}
	wait_threads(tid, threads);

#define _MIN(a, b) ((a) < (b) ? (a) : (b))
#define _MAX(a, b) ((a) < (b) ? (b) : (a))

	for (i = 0; i < threads; i++) {
		long ms = data[i].time_ms;

		sum += ms;
		min_ms = _MIN(min_ms, ms);
		max_ms = _MAX(max_ms, ms);
	}

	avg_ms = sum / threads;

	printf("%d %ld.%03ld %ld.%03ld %ld.%03ld\n", threads,
			avg_ms / 1000, avg_ms % 1000,
			min_ms / 1000, min_ms % 1000,
			max_ms / 1000, max_ms % 1000);

	if (verbose) {
		unsigned long long total_bytes;
		unsigned long long bytes_per_msec;

		total_bytes = value_length;
		total_bytes *= threads;
		total_bytes *= requests;

		bytes_per_msec = total_bytes / avg_ms;

		printf("Throughput: %llu KB/sec\n",
				bytes_per_msec * 1000UL / 1024UL);
	}

	free(data);
	free(tid);
}
static int
do_test (void)
{
  /* Limit the size of the process, so that memory allocation will
     fail without impacting the entire system.  */
  {
    struct rlimit limit;
    if (getrlimit (RLIMIT_AS, &limit) != 0)
      {
        printf ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n");
        return 1;
      }
    /* This limit, 800MB, is just a heuristic. Any value can be
       picked.  */
    long target = 800 * 1024 * 1024;
    if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
      {
        limit.rlim_cur = target;
        if (setrlimit (RLIMIT_AS, &limit) != 0)
          {
            printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n");
            return 1;
          }
      }
  }

  xpthread_attr_init (&detached);

  xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED);

  /* A large thread stack seems beneficial for reproducing a race
     condition in detached thread creation.  The goal is to reach the
     limit of the runtime thread stack cache such that the detached
     thread's stack is unmapped after exit and causes a segfault when
     the parent reads the thread descriptor data stored on the the
     unmapped stack.  */
  xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024);

  xpthread_barrier_init (&barrier, NULL, creator_threads);

  pthread_t threads[creator_threads];

  for (int i = 0; i < creator_threads; ++i)
    threads[i] = xpthread_create (NULL, creator_thread, NULL);

  for (int i = 0; i < creator_threads; ++i)
    xpthread_join (threads[i]);

  xpthread_attr_destroy (&detached);

  xpthread_barrier_destroy (&barrier);

  return 0;
}
Exemple #6
0
static struct worker_info *create_workers(struct benchmark_config *config,
		int thnum, const char *command, struct work_queue *in_queue,
		struct work_queue *out_queue)
{
	struct worker_info *data = xmalloc(sizeof(*data) * thnum);
	int i;

	for (i = 0; i < thnum; i++) {
		data[i].db = config->ops.open_db(config);
		data[i].config = config;
		data[i].command = command;
		data[i].in_queue = in_queue;
		data[i].out_queue = out_queue;
	}
	for (i = 0; i < thnum; i++)
		xpthread_create(&data[i].tid, benchmark_thread, &data[i]);

	return data;
}
Exemple #7
0
static int
do_test (void)
{
  xpthread_barrier_init (&barrier, NULL, thread_count + 1);

  pthread_t threads[thread_count];
  for (size_t i = 0; i < array_length (threads); ++i)
    threads[i] = xpthread_create (NULL, allocation_thread_function, NULL);

  xpthread_barrier_wait (&barrier);
  puts ("info: After allocation:");
  malloc_info (0, stdout);

  xpthread_barrier_wait (&barrier);
  for (size_t i = 0; i < array_length (threads); ++i)
    xpthread_join (threads[i]);

  puts ("\ninfo: After deallocation:");
  malloc_info (0, stdout);

  return 0;
}
Exemple #8
0
static int
do_test (void)
{
  unsigned int i;
  printf ("Starting %d threads to run %lld iterations.\n",
	  thread_count, iteration_count);

  pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t));
  xpthread_barrier_init (&barrier, NULL, thread_count);
  xpthread_mutex_init (&mutex, NULL);

  for (i = 0; i < thread_count; i++)
    threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i);

  for (i = 0; i < thread_count; i++)
    xpthread_join (threads[i]);

  xpthread_barrier_destroy (&barrier);
  free (threads);

  return EXIT_SUCCESS;
}
static int
do_test (void)
{
  /* The number of threads should be smaller than the number of
     arenas, so that there will be some free arenas to add to the
     arena free list.  */
  enum { outer_thread_count = 2 };
  if (mallopt (M_ARENA_MAX, 8) == 0)
    {
      printf ("error: mallopt (M_ARENA_MAX) failed\n");
      return 1;
    }

  /* Leave some room for shutting down all threads gracefully.  */
  int timeout = 3;
  if (timeout > DEFAULT_TIMEOUT)
    timeout = DEFAULT_TIMEOUT - 1;

  pthread_t *threads = xcalloc (sizeof (*threads), outer_thread_count);
  for (long i = 0; i < outer_thread_count; ++i)
    threads[i] = xpthread_create (NULL, outer_thread, NULL);

  struct timespec ts = {timeout, 0};
  if (nanosleep (&ts, NULL))
    {
      printf ("error: error: nanosleep: %m\n");
      abort ();
    }

  __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);

  for (long i = 0; i < outer_thread_count; ++i)
    xpthread_join (threads[i]);
  free (threads);

  return 0;
}
Exemple #10
0
static int
do_test (void)
{
    /* The test basically pipe a 'echo $$' created by a thread with a
       cancellation pending.  It then checks if the thread is not cancelled,
       the process is created and if the output is the expected one.  */

    if (pipe (pipefd) != 0)
    {
        puts ("error: pipe failed");
        exit (1);
    }

    /* Not interested in knowing when the pipe is closed.  */
    if (sigignore (SIGPIPE) != 0)
    {
        puts ("error: sigignore failed");
        exit (1);
    }

    /* To synchronize with the thread.  */
    if (pthread_barrier_init (&b, NULL, 2) != 0)
    {
        puts ("error: pthread_barrier_init failed");
        exit (1);
    }

    pthread_t th = xpthread_create (NULL, &tf, NULL);

    if (pthread_cancel (th) != 0)
    {
        puts ("error: pthread_cancel failed");
        return 1;
    }

    xpthread_barrier_wait (&b);

    if (xpthread_join (th) == PTHREAD_CANCELED)
    {
        puts ("error: thread cancelled");
        exit (1);
    }

    close (pipefd[1]);

    /* The global 'pid' should be set by thread posix_spawn calling.  Check
       below if it was executed correctly and with expected output.  */

    char buf[64];
    ssize_t n;
    bool seen_pid = false;
    while (TEMP_FAILURE_RETRY ((n = read (pipefd[0], buf, sizeof (buf)))) > 0)
    {
        /* We only expect to read the PID.  */
        char *endp;
        long int rpid = strtol (buf, &endp, 10);

        if (*endp != '\n')
        {
            printf ("error: didn't parse whole line: \"%s\"\n", buf);
            exit (1);
        }
        if (endp == buf)
        {
            puts ("error: read empty line");
            exit (1);
        }

        if (rpid != pid)
        {
            printf ("error: found \"%s\", expected PID %ld\n", buf,
                    (long int) pid);
            exit (1);
        }

        if (seen_pid)
        {
            puts ("error: found more than one PID line");
            exit (1);
        }

        seen_pid = true;
    }

    close (pipefd[0]);

    int status;
    int err = waitpid (pid, &status, 0);
    if (err != pid)
    {
        puts ("errnor: waitpid failed");
        exit (1);
    }

    if (!seen_pid)
    {
        puts ("error: didn't get PID");
        exit (1);
    }

    return 0;
}
Exemple #11
0
void start_daemon(int client) {
	// Launch the daemon, create new session, set proper context
	if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
		fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
		PLOGE("start daemon");
	}

	switch (fork()) {
	case -1:
		PLOGE("fork");
	case 0:
		break;
	default:
		return;
	}

	// First close the client, it's useless for us
	close(client);
	xsetsid();
	setcon("u:r:su:s0");
	umask(022);
	int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
	xdup2(fd, STDIN_FILENO);
	xdup2(fd, STDOUT_FILENO);
	xdup2(fd, STDERR_FILENO);
	close(fd);

	// Patch selinux with medium patch before we do anything
	load_policydb(SELINUX_POLICY);
	sepol_med_rules();
	dump_policydb(SELINUX_LOAD);

	// Continue the larger patch in another thread, we will join later
	pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL);

	struct sockaddr_un sun;
	fd = setup_socket(&sun);

	xbind(fd, (struct sockaddr*) &sun, sizeof(sun));
	xlisten(fd, 10);

	// Change process name
	strcpy(argv0, "magisk_daemon");
	// The root daemon should not do anything if an error occurs
	// It should stay intact under any circumstances
	err_handler = do_nothing;

	LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");

	// Unlock all blocks for rw
	unlock_blocks();

	// Setup links under /sbin
	xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
	create_links(NULL, "/sbin");
	xchmod("/sbin", 0755);
	xmkdir("/magisk", 0755);
	xchmod("/magisk", 0755);
	xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);

	// Loop forever to listen for requests
	while(1) {
		int *client = xmalloc(sizeof(int));
		*client = xaccept4(fd, NULL, NULL, SOCK_CLOEXEC);
		pthread_t thread;
		xpthread_create(&thread, NULL, request_handler, client);
		// Detach the thread, we will never join it
		pthread_detach(thread);
	}
}