Skip to content

Commit 4891fab

Browse files
committed
add fork support, like linux kernel, every process has one freebsd struct thread
1 parent e284dbd commit 4891fab

File tree

14 files changed

+437
-4
lines changed

14 files changed

+437
-4
lines changed

adapter/syscall/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ endif
2525
# Use for some scenarios similar to Nginx.
2626
#FF_KERNEL_EVENT=1
2727

28+
# If enable FF_USE_THREAD_STRUCT_HANDLE, every ff_so_context has one struct thread handle in fstack, fork will be supported
29+
# like linux kernel.
30+
#FF_USE_THREAD_STRUCT_HANDLE=1
31+
2832
PKGCONF ?= pkg-config
2933

3034
ifndef DEBUG
@@ -49,6 +53,10 @@ ifdef FF_PRELOAD_POLLING_MODE
4953
CFLAGS+= -DFF_PRELOAD_POLLING_MODE
5054
endif
5155

56+
ifdef FF_USE_THREAD_STRUCT_HANDLE
57+
CFLAGS+= -DFF_USE_THREAD_STRUCT_HANDLE
58+
endif
59+
5260
CFLAGS += -fPIC -Wall -Werror $(shell $(PKGCONF) --cflags libdpdk)
5361

5462
INCLUDES= -I. -I${FF_PATH}/lib

adapter/syscall/ff_adapter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
int ff_adapter_init();
1111
//int __attribute__((constructor)) ff_adapter_init(int argc, char * const argv[]);
1212

13+
int ff_adapter_child_process_init(void);
14+
1315
void alarm_event_sem();
1416

1517
/*-

adapter/syscall/ff_hook_syscall.c

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,13 +2137,39 @@ ff_hook_fork(void)
21372137
#ifdef FF_MULTI_SC
21382138
current_worker_id++;
21392139
ERR_LOG("parent process, current_worker_id++:%d\n", current_worker_id);
2140+
#endif
2141+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2142+
sc->forking = 1;
2143+
/* Loop until child fork done. */
2144+
while (sc->forking);
21402145
#endif
21412146
}
21422147
else if (pid == 0) {
21432148
ERR_LOG("chilid process, sc:%p, sc->refcount:%d, ff_so_zone:%p\n",
21442149
sc, sc->refcount, ff_so_zone);
21452150
#ifdef FF_MULTI_SC
21462151
ERR_LOG("chilid process, current_worker_id:%d\n", current_worker_id);
2152+
#endif
2153+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2154+
struct ff_so_context *parent_sc = sc;
2155+
2156+
/* Child process attach new sc */
2157+
ff_adapter_child_process_init();
2158+
2159+
/*
2160+
* The fork system call duplicates the file
2161+
* descriptors that were open in the parent process
2162+
*/
2163+
DEFINE_REQ_ARGS(fork);
2164+
args->parent_thread_handle = parent_sc->ff_thread_handle;
2165+
/* Output value */
2166+
args->child_thread_handle = NULL;
2167+
SYSCALL(FF_SO_FORK, args);
2168+
if (ret == 0) {
2169+
sc->ff_thread_handle = args->child_thread_handle;
2170+
}
2171+
2172+
parent_sc->forking = 0;
21472173
#endif
21482174
}
21492175

@@ -2442,6 +2468,16 @@ thread_destructor(void *sc)
24422468
}
24432469
}
24442470

2471+
static inline int
2472+
ff_application_exit(struct ff_so_context *sc)
2473+
{
2474+
DEFINE_REQ_ARGS(exit_application);
2475+
args->sc = sc;
2476+
SYSCALL(FF_SO_EXIT_APPLICATION, args);
2477+
2478+
return ret;
2479+
}
2480+
24452481
void __attribute__((destructor))
24462482
ff_adapter_exit()
24472483
{
@@ -2455,13 +2491,19 @@ ff_adapter_exit()
24552491
for (i = 0; i < worker_id; i++) {
24562492
ERR_LOG("pthread self tid:%lu, detach sc:%p\n", pthread_self(), scs[i].sc);
24572493
ff_so_zone = ff_so_zones[i];
2458-
ff_detach_so_context(scs[i].sc);
2494+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2495+
ff_application_exit(scs[i].sc);
2496+
#endif
2497+
ff_detach_so_context(scs[i].sc);
24592498
}
24602499
} else
24612500
#endif
24622501
{
24632502
ERR_LOG("pthread self tid:%lu, detach sc:%p\n", pthread_self(), sc);
2464-
ff_detach_so_context(sc);
2503+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2504+
ff_application_exit(sc);
2505+
#endif
2506+
ff_detach_so_context(sc);
24652507
sc = NULL;
24662508
}
24672509
#endif
@@ -2618,11 +2660,40 @@ ff_adapter_init()
26182660

26192661
rte_spinlock_unlock(&worker_id_lock);
26202662

2663+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2664+
/*
2665+
* Request to fstack, alloc sc->ff_thread_handle
2666+
* Every appliaction
2667+
*/
2668+
{
2669+
DEFINE_REQ_ARGS(register_application);
2670+
args->sc = sc;
2671+
SYSCALL(FF_SO_REGISTER_APPLICATION, args);
2672+
if (ret < 0) {
2673+
return -1;
2674+
}
2675+
}
2676+
#endif
2677+
26212678
ERR_LOG("ff_adapter_init success, sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
26222679

26232680
return 0;
26242681
}
26252682

2683+
int
2684+
ff_adapter_child_process_init(void)
2685+
{
2686+
sc = ff_attach_so_context(0);
2687+
if (sc == NULL) {
2688+
ERR_LOG("ff_attach_so_context failed\n");
2689+
return -1;
2690+
}
2691+
2692+
ERR_LOG("ff_adapter_child_process_init success, sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
2693+
2694+
return 0;
2695+
}
2696+
26262697
void
26272698
alarm_event_sem()
26282699
{

adapter/syscall/ff_so_zone.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ ff_create_so_memzone()
9595
sc->status = FF_SC_IDLE;
9696
sc->idx = i;
9797
sc->refcount = 0;
98+
sc->ff_thread_handle = NULL;
9899
//so_zone_tmp->inuse[i] = 0;
99100

100101
if (sem_init(&sc->wait_sem, 1, 0) == -1) {

adapter/syscall/ff_socket_ops.c

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,41 @@ ff_sys_kevent(struct ff_kevent_args *args)
370370
static pid_t
371371
ff_sys_fork(struct ff_fork_args *args)
372372
{
373-
errno = ENOSYS;
374-
return -1;
373+
void *parent = args->parent_thread_handle;
374+
/*
375+
* Linux has performed a real fork, and at this point,
376+
* we simply need to create a new thread and duplicate the file descriptors
377+
* that the parent process has already opened.
378+
*/
379+
if (parent) {
380+
args->child_thread_handle = ff_adapt_user_thread_add(parent);
381+
}
382+
383+
return 0;
384+
}
385+
386+
static int
387+
ff_sys_register_thread(struct ff_register_application_args *args)
388+
{
389+
/* New user application, use default thread0 */
390+
args->sc->ff_thread_handle = ff_adapt_user_thread_add(NULL);
391+
392+
if (args->sc->ff_thread_handle == NULL) {
393+
return -1;
394+
}
395+
396+
return 0;
397+
}
398+
399+
static int
400+
ff_sys_exit_thread(struct ff_exit_application_args *args)
401+
{
402+
/* Exit user application */
403+
if (args->sc->ff_thread_handle) {
404+
ff_adapt_user_thread_exit(args->sc->ff_thread_handle);
405+
}
406+
407+
return 0;
375408
}
376409

377410
static int
@@ -439,6 +472,10 @@ ff_so_handler(int ops, void *args)
439472
return ff_sys_kevent((struct ff_kevent_args *)args);
440473
case FF_SO_FORK:
441474
return ff_sys_fork((struct ff_fork_args *)args);
475+
case FF_SO_REGISTER_APPLICATION:
476+
return ff_sys_register_thread((struct ff_register_application_args *)args);
477+
case FF_SO_EXIT_APPLICATION:
478+
return ff_sys_exit_thread((struct ff_exit_application_args *)args);
442479
default:
443480
break;
444481
}
@@ -451,6 +488,11 @@ ff_so_handler(int ops, void *args)
451488
static inline void
452489
ff_handle_socket_ops(struct ff_so_context *sc)
453490
{
491+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
492+
void *old_thread;
493+
void *ff_thread_handle = sc->ff_thread_handle;
494+
#endif
495+
454496
if (!rte_spinlock_trylock(&sc->lock)) {
455497
return;
456498
}
@@ -463,7 +505,17 @@ ff_handle_socket_ops(struct ff_so_context *sc)
463505
DEBUG_LOG("ff_handle_socket_ops sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
464506

465507
errno = 0;
508+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
509+
if (ff_thread_handle) {
510+
old_thread = ff_switch_curthread(ff_thread_handle);
511+
}
512+
#endif
466513
sc->result = ff_so_handler(sc->ops, sc->args);
514+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
515+
if (ff_thread_handle) {
516+
ff_restore_curthread(old_thread);
517+
}
518+
#endif
467519
sc->error = errno;
468520
DEBUG_LOG("ff_handle_socket_ops error:%d, ops:%d, result:%d\n", errno, sc->ops, sc->result);
469521

adapter/syscall/ff_socket_ops.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ enum FF_SOCKET_OPS {
6464
FF_SO_KQUEUE,
6565
FF_SO_KEVENT,
6666
FF_SO_FORK, // 29
67+
FF_SO_REGISTER_APPLICATION,
68+
FF_SO_EXIT_APPLICATION,
6769
};
6870

6971
enum FF_SO_CONTEXT_STATUS {
@@ -110,6 +112,8 @@ struct ff_so_context {
110112
/* CACHE LINE 1 */
111113
/* listen fd, refcount.. */
112114
int refcount;
115+
void *ff_thread_handle;
116+
volatile int forking;
113117
} __attribute__((aligned(RTE_CACHE_LINE_SIZE)));
114118

115119
extern __FF_THREAD struct ff_socket_ops_zone *ff_so_zone;

adapter/syscall/ff_sysproto.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,16 @@ struct ff_kevent_args {
191191
};
192192

193193
struct ff_fork_args {
194+
void *parent_thread_handle;
195+
void *child_thread_handle;
196+
};
197+
198+
struct ff_register_application_args {
199+
struct ff_so_context *sc;
200+
};
194201

202+
struct ff_exit_application_args {
203+
struct ff_so_context *sc;
195204
};
196205

197206
#endif

freebsd/kern/kern_descrip.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,6 +2516,82 @@ fdclearlocks(struct thread *td)
25162516
free(fdtol, M_FILEDESC_TO_LEADER);
25172517
}
25182518

2519+
/*
2520+
* Release a filedesc structure, we use this.
2521+
*/
2522+
static void
2523+
fdescfree_fds_adapt_use(struct thread *td, struct filedesc *fdp, bool needclose)
2524+
{
2525+
struct filedesc0 *fdp0;
2526+
struct freetable *ft, *tft;
2527+
struct filedescent *fde;
2528+
struct file *fp;
2529+
int i, lastfile;
2530+
2531+
KASSERT(refcount_load(&fdp->fd_refcnt) == 0,
2532+
("%s: fd table %p carries references", __func__, fdp));
2533+
2534+
/*
2535+
* Serialize with threads iterating over the table, if any.
2536+
*/
2537+
if (refcount_load(&fdp->fd_holdcnt) > 1) {
2538+
FILEDESC_XLOCK(fdp);
2539+
FILEDESC_XUNLOCK(fdp);
2540+
}
2541+
2542+
lastfile = fdlastfile_single(fdp);
2543+
for (i = 0; i <= lastfile; i++) {
2544+
fde = &fdp->fd_ofiles[i];
2545+
fp = fde->fde_file;
2546+
if (fp != NULL) {
2547+
fdefree_last(fde);
2548+
if (needclose)
2549+
(void) closefp_impl(fdp, i, fp, td, true);
2550+
else
2551+
fdrop(fp, td);
2552+
}
2553+
}
2554+
2555+
if (NDSLOTS(fdp->fd_nfiles) > NDSLOTS(NDFILE))
2556+
free(fdp->fd_map, M_FILEDESC);
2557+
if (fdp->fd_nfiles > NDFILE)
2558+
free(fdp->fd_files, M_FILEDESC);
2559+
2560+
fdp0 = (struct filedesc0 *)fdp;
2561+
SLIST_FOREACH_SAFE(ft, &fdp0->fd_free, ft_next, tft)
2562+
free(ft->ft_table, M_FILEDESC);
2563+
2564+
fddrop(fdp);
2565+
}
2566+
2567+
void
2568+
fdescfree_adapt_use(struct thread *td)
2569+
{
2570+
struct proc *p;
2571+
struct filedesc *fdp;
2572+
2573+
p = td->td_proc;
2574+
fdp = p->p_fd;
2575+
MPASS(fdp != NULL);
2576+
2577+
#ifdef RACCT
2578+
if (RACCT_ENABLED())
2579+
racct_set_unlocked(p, RACCT_NOFILE, 0);
2580+
#endif
2581+
2582+
if (p->p_fdtol != NULL)
2583+
fdclearlocks(td);
2584+
2585+
if (refcount_release(&fdp->fd_refcnt) == 0)
2586+
return;
2587+
2588+
fdescfree_fds_adapt_use(td, fdp, 1);
2589+
2590+
PROC_LOCK(p);
2591+
p->p_fd = NULL;
2592+
PROC_UNLOCK(p);
2593+
}
2594+
25192595
/*
25202596
* Release a filedesc structure.
25212597
*/

freebsd/sys/filedesc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ int fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds,
255255
void fdinstall_remapped(struct thread *td, struct filedesc *fdp);
256256
void fdunshare(struct thread *td);
257257
void fdescfree(struct thread *td);
258+
void fdescfree_adapt_use(struct thread *td);
258259
void fdescfree_remapped(struct filedesc *fdp);
259260
int fdlastfile(struct filedesc *fdp);
260261
int fdlastfile_single(struct filedesc *fdp);

lib/ff_api.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,18 @@ int ff_zc_mbuf_write(struct ff_zc_mbuf *m, const char *data, int len);
356356
*/
357357
int ff_zc_mbuf_read(struct ff_zc_mbuf *m, const char *data, int len);
358358

359+
/*
360+
* Create user thread context for LD_PRELOAD mode.
361+
* It saved in ff_so_context.
362+
*/
363+
void *ff_adapt_user_thread_add(void *parent);
364+
365+
void ff_adapt_user_thread_exit(void *td);
366+
367+
void *ff_switch_curthread(void *new_curthread);
368+
369+
void ff_restore_curthread(void *old_curthread);
370+
359371
/* ZERO COPY API end */
360372

361373
#ifdef __cplusplus

0 commit comments

Comments
 (0)