}
}
+static void *frr_pthread_attr_non_controlled_start(void *arg)
+{
+ struct frr_pthread *fpt = arg;
+
+ fpt->running = true;
+
+ return NULL;
+}
+
+/* Create a FRR pthread context from a non FRR pthread initialized from an
+ * external library in order to allow logging */
+int frr_pthread_non_controlled_startup(pthread_t thread, const char *name,
+ const char *os_name)
+{
+ struct frr_pthread_attr attr = {
+ .start = frr_pthread_attr_non_controlled_start,
+ .stop = frr_pthread_attr_default.stop,
+ };
+ struct frr_pthread *fpt;
+
+ fpt = frr_pthread_new(&attr, name, os_name);
+ if (!fpt)
+ return -1;
+
+ fpt->thread = thread;
+ fpt->rcu_thread = rcu_thread_new(NULL);
+ frr_pthread_inner(fpt);
+
+ return 0;
+}
+
/*
* ----------------------------------------------------------------------------
* Default Event Loop
#define pthread_condattr_setclock(A, B)
#endif
+int frr_pthread_non_controlled_startup(pthread_t thread, const char *name,
+ const char *os_name);
+
/* mutex auto-lock/unlock */
/* variant 1:
return (struct rcu_thread *)pthread_getspecific(rcu_thread_key);
}
-/*
- * thread management (for the non-main thread)
- */
-struct rcu_thread *rcu_thread_prepare(void)
+struct rcu_thread *rcu_thread_new(void *arg)
{
- struct rcu_thread *rt, *cur;
-
- rcu_assert_read_locked();
-
- if (!rcu_active)
- rcu_start();
-
- cur = rcu_self();
- assert(cur->depth);
+ struct rcu_thread *rt, *cur = arg;
/* new thread always starts with rcu_read_lock held at depth 1, and
* holding the same epoch as the parent (this makes it possible to
rt->depth = 1;
seqlock_init(&rt->rcu);
- seqlock_acquire(&rt->rcu, &cur->rcu);
+ if (cur)
+ seqlock_acquire(&rt->rcu, &cur->rcu);
rcu_threads_add_tail(&rcu_threads, rt);
return rt;
}
+/*
+ * thread management (for the non-main thread)
+ */
+struct rcu_thread *rcu_thread_prepare(void)
+{
+ struct rcu_thread *cur;
+
+ rcu_assert_read_locked();
+
+ if (!rcu_active)
+ rcu_start();
+
+ cur = rcu_self();
+ assert(cur->depth);
+
+ return rcu_thread_new(cur);
+}
+
void rcu_thread_start(struct rcu_thread *rt)
{
pthread_setspecific(rcu_thread_key, rt);
/* opaque */
struct rcu_thread;
+/* sets up rcu thread info
+ *
+ * return value must be passed into the thread's call to rcu_thread_start()
+ */
+extern struct rcu_thread *rcu_thread_new(void *arg);
+
/* called before new thread creation, sets up rcu thread info for new thread
* before it actually exits. This ensures possible RCU references are held
* for thread startup.