+ if (error == -1)
+ return(errno);
+ return(0);
+}
+
+void
+pthread_workqueue_atfork_prepare(void)
+{
+ /*
+ * NOTE: Any workq additions here
+ * should be for i386,x86_64 only
+ */
+ dispatch_atfork_prepare();
+}
+
+void
+pthread_workqueue_atfork_parent(void)
+{
+ /*
+ * NOTE: Any workq additions here
+ * should be for i386,x86_64 only
+ */
+ dispatch_atfork_parent();
+}
+
+void
+pthread_workqueue_atfork_child(void)
+{
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ pthread_t self = pthread_self();
+
+ __workqueue_list_lock = OS_SPINLOCK_INIT;
+
+ /* already using new spis? */
+ if (__workqueue_newspis != 0) {
+ /* prepare the kernel for workq action */
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ __bsdthread_register(thread_start, start_wqthread, round_page(sizeof(struct _pthread)), _pthread_start, &workq_targetconc[0], (uintptr_t)(&self->tsd[__PTK_LIBDISPATCH_KEY0]) - (uintptr_t)(&self->tsd[0]));
+#else
+ __bsdthread_register(_pthread_start, _pthread_wqthread, round_page(sizeof(struct _pthread)),NULL,NULL,0);
+#endif
+ (void)__workq_open();
+ kernel_workq_setup = 1;
+ return;
+ }
+
+ /* not using old spis either? */
+ if (__workqueue_oldspis == 0)
+ return;
+
+ /*
+ * NOTE: workq additions here
+ * are for i386,x86_64 only as
+ * ppc and arm do not support it
+ */
+ if (kernel_workq_setup != 0){
+ kernel_workq_setup = 0;
+ _pthread_work_internal_init();
+ }
+#endif
+ dispatch_atfork_child();
+}
+
+static int
+_pthread_work_internal_init(void)
+{
+ int i, error;
+ pthread_workqueue_head_t headp;
+ pthread_workqueue_t wq;
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ pthread_t self = pthread_self();
+#endif
+
+ if (kernel_workq_setup == 0) {
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+ __bsdthread_register(thread_start, start_wqthread, round_page(sizeof(struct _pthread)), _pthread_start, &workq_targetconc[0], (uintptr_t)(&self->tsd[__PTK_LIBDISPATCH_KEY0]) - (uintptr_t)(&self->tsd[0]));
+#else
+ __bsdthread_register(_pthread_start, _pthread_wqthread, round_page(sizeof(struct _pthread)),NULL,NULL,0);
+#endif
+
+ _pthread_wq_attr_default.queueprio = WORKQ_DEFAULT_PRIOQUEUE;
+ _pthread_wq_attr_default.sig = PTHREAD_WORKQUEUE_ATTR_SIG;
+
+ for( i = 0; i< WORKQ_NUM_PRIOQUEUE; i++) {
+ headp = __pthread_wq_head_tbl[i];
+ TAILQ_INIT(&headp->wqhead);
+ headp->next_workq = 0;
+ }
+
+ __workqueue_pool_ptr = NULL;
+ __workqueue_pool_size = round_page(sizeof(struct _pthread_workitem) * WORKITEM_POOL_SIZE);
+
+ __workqueue_pool_ptr = (struct _pthread_workitem *)mmap(NULL, __workqueue_pool_size,
+ PROT_READ|PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE,
+ 0,
+ 0);
+
+ if (__workqueue_pool_ptr == MAP_FAILED) {
+ /* Not expected to fail, if it does, always malloc for work items */
+ __workqueue_nitems = WORKITEM_POOL_SIZE;
+ __workqueue_pool_ptr = NULL;
+ } else
+ __workqueue_nitems = 0;
+
+ /* sets up the workitem pool */
+ grow_workitem();
+
+ /* since the size is less than a page, leaving this in malloc pool */
+ wq = (struct _pthread_workqueue *)malloc(sizeof(struct _pthread_workqueue) * WORKQUEUE_POOL_SIZE);
+ bzero(wq, (sizeof(struct _pthread_workqueue) * WORKQUEUE_POOL_SIZE));