aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic/odp_thread.c
blob: ccbd0685b64078575744f6632040c1ba5e632f58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* Copyright (c) 2013, Linaro Limited
 * All rights reserved.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sched.h>

#include <odp_thread.h>
#include <odp_internal.h>
#include <odp_atomic.h>
#include <odp_config.h>
#include <odp_debug_internal.h>
#include <odp_shared_memory.h>
#include <odp_align.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


typedef struct {
	int thr_id;
	int cpu;

} thread_state_t;


typedef struct {
	thread_state_t   thr[ODP_CONFIG_MAX_THREADS];
	odp_atomic_u32_t num;
	odp_atomic_u32_t next_id;

} thread_globals_t;


/* Globals */
static thread_globals_t *thread_globals;


/* Thread local */
static __thread thread_state_t *this_thread;


int odp_thread_init_global(void)
{
	odp_shm_t shm;

	shm = odp_shm_reserve("odp_thread_globals",
			      sizeof(thread_globals_t),
			      ODP_CACHE_LINE_SIZE, 0);

	thread_globals = odp_shm_addr(shm);

	if (thread_globals == NULL)
		return -1;

	memset(thread_globals, 0, sizeof(thread_globals_t));
	odp_atomic_init_u32(&thread_globals->next_id, 0);
	odp_atomic_init_u32(&thread_globals->num, 0);
	return 0;
}


static int thread_id(void)
{
	uint32_t id;
	int cpu;

	id = odp_atomic_fetch_inc_u32(&thread_globals->next_id);

	if (id >= ODP_CONFIG_MAX_THREADS) {
		ODP_ERR("Too many threads\n");
		return -1;
	}
	odp_atomic_inc_u32(&thread_globals->num);

	cpu = sched_getcpu();

	if (cpu < 0) {
		ODP_ERR("getcpu failed\n");
		return -1;
	}

	thread_globals->thr[id].thr_id = id;
	thread_globals->thr[id].cpu    = cpu;

	return id;
}

int odp_thread_init_local(void)
{
	int id;

	id = thread_id();

	if (id < 0)
		return -1;

	this_thread = &thread_globals->thr[id];
	return 0;
}

int odp_thread_term_local(void)
{
	uint32_t num;
	num = odp_atomic_fetch_dec_u32(&thread_globals->num);
	ODP_ASSERT(num > 0, "Number of threads should be > 0");
	return num - 1; /* return a number of threads left */
}

int odp_thread_id(void)
{
	return this_thread->thr_id;
}


int odp_thread_cpu(void)
{
	return this_thread->cpu;
}