Skip to content

Commit 2869cbf

Browse files
authored
Merge pull request #887 from liujinhui-job/add-new-fork-implementation-method
add fork support, like linux kernel, every process has one freebsd struct thread
2 parents 403faf3 + 4891fab commit 2869cbf

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
@@ -2303,13 +2303,39 @@ ff_hook_fork(void)
23032303
#ifdef FF_MULTI_SC
23042304
current_worker_id++;
23052305
ERR_LOG("parent process, current_worker_id++:%d\n", current_worker_id);
2306+
#endif
2307+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2308+
sc->forking = 1;
2309+
/* Loop until child fork done. */
2310+
while (sc->forking);
23062311
#endif
23072312
}
23082313
else if (pid == 0) {
23092314
ERR_LOG("chilid process, sc:%p, sc->refcount:%d, ff_so_zone:%p\n",
23102315
sc, sc->refcount, ff_so_zone);
23112316
#ifdef FF_MULTI_SC
23122317
ERR_LOG("chilid process, current_worker_id:%d\n", current_worker_id);
2318+
#endif
2319+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2320+
struct ff_so_context *parent_sc = sc;
2321+
2322+
/* Child process attach new sc */
2323+
ff_adapter_child_process_init();
2324+
2325+
/*
2326+
* The fork system call duplicates the file
2327+
* descriptors that were open in the parent process
2328+
*/
2329+
DEFINE_REQ_ARGS(fork);
2330+
args->parent_thread_handle = parent_sc->ff_thread_handle;
2331+
/* Output value */
2332+
args->child_thread_handle = NULL;
2333+
SYSCALL(FF_SO_FORK, args);
2334+
if (ret == 0) {
2335+
sc->ff_thread_handle = args->child_thread_handle;
2336+
}
2337+
2338+
parent_sc->forking = 0;
23132339
#endif
23142340
}
23152341

@@ -2608,6 +2634,16 @@ thread_destructor(void *sc)
26082634
}
26092635
}
26102636

2637+
static inline int
2638+
ff_application_exit(struct ff_so_context *sc)
2639+
{
2640+
DEFINE_REQ_ARGS(exit_application);
2641+
args->sc = sc;
2642+
SYSCALL(FF_SO_EXIT_APPLICATION, args);
2643+
2644+
return ret;
2645+
}
2646+
26112647
void __attribute__((destructor))
26122648
ff_adapter_exit()
26132649
{
@@ -2621,13 +2657,19 @@ ff_adapter_exit()
26212657
for (i = 0; i < worker_id; i++) {
26222658
ERR_LOG("pthread self tid:%lu, detach sc:%p\n", pthread_self(), scs[i].sc);
26232659
ff_so_zone = ff_so_zones[i];
2624-
ff_detach_so_context(scs[i].sc);
2660+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2661+
ff_application_exit(scs[i].sc);
2662+
#endif
2663+
ff_detach_so_context(scs[i].sc);
26252664
}
26262665
} else
26272666
#endif
26282667
{
26292668
ERR_LOG("pthread self tid:%lu, detach sc:%p\n", pthread_self(), sc);
2630-
ff_detach_so_context(sc);
2669+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2670+
ff_application_exit(sc);
2671+
#endif
2672+
ff_detach_so_context(sc);
26312673
sc = NULL;
26322674
}
26332675
#endif
@@ -2784,11 +2826,40 @@ ff_adapter_init()
27842826

27852827
rte_spinlock_unlock(&worker_id_lock);
27862828

2829+
#ifdef FF_USE_THREAD_STRUCT_HANDLE
2830+
/*
2831+
* Request to fstack, alloc sc->ff_thread_handle
2832+
* Every appliaction
2833+
*/
2834+
{
2835+
DEFINE_REQ_ARGS(register_application);
2836+
args->sc = sc;
2837+
SYSCALL(FF_SO_REGISTER_APPLICATION, args);
2838+
if (ret < 0) {
2839+
return -1;
2840+
}
2841+
}
2842+
#endif
2843+
27872844
ERR_LOG("ff_adapter_init success, sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
27882845

27892846
return 0;
27902847
}
27912848

2849+
int
2850+
ff_adapter_child_process_init(void)
2851+
{
2852+
sc = ff_attach_so_context(0);
2853+
if (sc == NULL) {
2854+
ERR_LOG("ff_attach_so_context failed\n");
2855+
return -1;
2856+
}
2857+
2858+
ERR_LOG("ff_adapter_child_process_init success, sc:%p, status:%d, ops:%d\n", sc, sc->status, sc->ops);
2859+
2860+
return 0;
2861+
}
2862+
27922863
void
27932864
alarm_event_sem()
27942865
{

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)