2 Utilities and interfaces for managing POSIX threads
3 Copyright (C) 2017 Cumulus Networks
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
24 #include "frr_pthread.h"
28 DEFINE_MTYPE_STATIC(LIB
, FRR_PTHREAD
, "FRR POSIX Thread");
30 static unsigned int next_id
= 0;
32 /* Hash table of all frr_pthreads along with synchronization primitive(s) and
33 * hash table callbacks.
34 * ------------------------------------------------------------------------ */
35 static struct hash
*pthread_table
;
36 static pthread_mutex_t pthread_table_mtx
= PTHREAD_MUTEX_INITIALIZER
;
38 /* pthread_table->hash_cmp */
39 static int pthread_table_hash_cmp(const void *value1
, const void *value2
)
41 const struct frr_pthread
*tq1
= value1
;
42 const struct frr_pthread
*tq2
= value2
;
44 return (tq1
->id
== tq2
->id
);
47 /* pthread_table->hash_key */
48 static unsigned int pthread_table_hash_key(void *value
)
50 return ((struct frr_pthread
*)value
)->id
;
52 /* ------------------------------------------------------------------------ */
54 void frr_pthread_init()
56 pthread_mutex_lock(&pthread_table_mtx
);
59 hash_create(pthread_table_hash_key
, pthread_table_hash_cmp
);
61 pthread_mutex_unlock(&pthread_table_mtx
);
64 void frr_pthread_finish()
66 pthread_mutex_lock(&pthread_table_mtx
);
68 hash_clean(pthread_table
, (void (*)(void *))frr_pthread_destroy
);
69 hash_free(pthread_table
);
71 pthread_mutex_unlock(&pthread_table_mtx
);
74 struct frr_pthread
*frr_pthread_new(const char *name
, unsigned int id
,
75 void *(*start_routine
) (void *),
76 int (*stop_routine
) (void **, struct frr_pthread
*))
78 static struct frr_pthread holder
= { 0 };
79 struct frr_pthread
*fpt
= NULL
;
81 pthread_mutex_lock(&pthread_table_mtx
);
85 if (!hash_lookup(pthread_table
, &holder
)) {
86 struct frr_pthread
*fpt
=
87 XCALLOC(MTYPE_FRR_PTHREAD
,
88 sizeof(struct frr_pthread
));
90 fpt
->master
= thread_master_create();
91 fpt
->start_routine
= start_routine
;
92 fpt
->stop_routine
= stop_routine
;
93 fpt
->name
= XSTRDUP(MTYPE_FRR_PTHREAD
, name
);
95 hash_get(pthread_table
, fpt
, hash_alloc_intern
);
98 pthread_mutex_unlock(&pthread_table_mtx
);
103 void frr_pthread_destroy(struct frr_pthread
*fpt
)
105 thread_master_free(fpt
->master
);
106 XFREE(MTYPE_FRR_PTHREAD
, fpt
->name
);
107 XFREE(MTYPE_FRR_PTHREAD
, fpt
);
110 struct frr_pthread
*frr_pthread_get(unsigned int id
)
112 static struct frr_pthread holder
= { 0 };
113 struct frr_pthread
*fpt
;
115 pthread_mutex_lock(&pthread_table_mtx
);
118 fpt
= hash_lookup(pthread_table
, &holder
);
120 pthread_mutex_unlock(&pthread_table_mtx
);
125 int frr_pthread_run(unsigned int id
, const pthread_attr_t
* attr
, void *arg
)
127 struct frr_pthread
*fpt
= frr_pthread_get(id
);
133 ret
= pthread_create(&fpt
->thread
, attr
, fpt
->start_routine
, arg
);
135 /* Per pthread_create(3), the contents of fpt->thread are undefined if
136 * pthread_create() did not succeed. Reset this value to zero. */
138 memset(&fpt
->thread
, 0x00, sizeof(fpt
->thread
));
144 * Calls the stop routine for the frr_pthread and resets any relevant fields.
146 * @param fpt - the frr_pthread to stop
147 * @param result - pointer to result pointer
148 * @return the return code from the stop routine
150 static int frr_pthread_stop_actual(struct frr_pthread
*fpt
, void **result
)
152 int ret
= (*fpt
->stop_routine
) (result
, fpt
);
153 memset(&fpt
->thread
, 0x00, sizeof(fpt
->thread
));
157 int frr_pthread_stop(unsigned int id
, void **result
)
159 struct frr_pthread
*fpt
= frr_pthread_get(id
);
160 return frr_pthread_stop_actual(fpt
, result
);
164 * Callback for hash_iterate to stop all frr_pthread's.
166 static void frr_pthread_stop_all_iter(struct hash_backet
*hb
, void *arg
)
168 struct frr_pthread
*fpt
= hb
->data
;
169 frr_pthread_stop_actual(fpt
, NULL
);
172 void frr_pthread_stop_all()
174 pthread_mutex_lock(&pthread_table_mtx
);
176 hash_iterate(pthread_table
, frr_pthread_stop_all_iter
, NULL
);
178 pthread_mutex_unlock(&pthread_table_mtx
);
181 unsigned int frr_pthread_get_id()