| 89 | nosanitize_address |
| 90 | #endif |
| 91 | pid_t sim_fork(const xcpt_reg_t *context) |
| 92 | { |
| 93 | struct tcb_s *parent = this_task(); |
| 94 | struct tcb_s *child; |
| 95 | unsigned char *pout; |
| 96 | unsigned char *pin; |
| 97 | xcpt_reg_t newsp; |
| 98 | xcpt_reg_t newfp; |
| 99 | xcpt_reg_t newtop; |
| 100 | xcpt_reg_t stacktop; |
| 101 | xcpt_reg_t stackutil; |
| 102 | |
| 103 | sinfo("fork context [%p]:\n", context); |
| 104 | sinfo(" frame pointer:%zx sp:%zx pc:%zx\n", |
| 105 | context[JB_FP], context[JB_SP], context[JB_PC]); |
| 106 | |
| 107 | /* Allocate and initialize a TCB for the child task. */ |
| 108 | |
| 109 | child = nxtask_setup_fork((start_t)context[JB_PC]); |
| 110 | if (!child) |
| 111 | { |
| 112 | serr("ERROR: nxtask_setup_fork failed\n"); |
| 113 | return (pid_t)ERROR; |
| 114 | } |
| 115 | |
| 116 | sinfo("TCBs: Parent=%p Child=%p\n", parent, child); |
| 117 | |
| 118 | /* How much of the parent's stack was utilized? The ARM uses |
| 119 | * a push-down stack so that the current stack pointer should |
| 120 | * be lower than the initial, adjusted stack pointer. The |
| 121 | * stack usage should be the difference between those two. |
| 122 | */ |
| 123 | |
| 124 | stacktop = (xcpt_reg_t)parent->stack_base_ptr + |
| 125 | parent->adj_stack_size; |
| 126 | DEBUGASSERT(stacktop > context[JB_SP]); |
| 127 | stackutil = stacktop - context[JB_SP]; |
| 128 | |
| 129 | sinfo("Parent: stackutil:%zu\n", stackutil); |
| 130 | |
| 131 | /* Make some feeble effort to preserve the stack contents. This is |
| 132 | * feeble because the stack surely contains invalid pointers and other |
| 133 | * content that will not work in the child context. However, if the |
| 134 | * user follows all of the caveats of fork() usage, even this feeble |
| 135 | * effort is overkill. |
| 136 | */ |
| 137 | |
| 138 | newtop = (xcpt_reg_t)child->stack_base_ptr + |
| 139 | child->adj_stack_size; |
| 140 | newsp = newtop - stackutil; |
| 141 | pout = (unsigned char *)newsp; |
| 142 | pin = (unsigned char *)context[JB_SP]; |
| 143 | while (stackutil-- > 0) *pout++ = *pin++; |
| 144 | |
| 145 | /* Was there a frame pointer in place before? */ |
| 146 | |
| 147 | if (context[JB_FP] >= context[JB_SP] && context[JB_FP] < stacktop) |
| 148 | { |
nothing calls this directly
no test coverage detected