initPHPThreads starts the main PHP thread, a fixed number of inactive PHP threads and reserves a fixed number of possible PHP threads
(numThreads int, numMaxThreads int, phpIni map[string]string)
| 35 | // a fixed number of inactive PHP threads |
| 36 | // and reserves a fixed number of possible PHP threads |
| 37 | func initPHPThreads(numThreads int, numMaxThreads int, phpIni map[string]string) (*phpMainThread, error) { |
| 38 | mainThread = &phpMainThread{ |
| 39 | state: state.NewThreadState(), |
| 40 | done: make(chan struct{}), |
| 41 | numThreads: numThreads, |
| 42 | maxThreads: numMaxThreads, |
| 43 | phpIni: phpIni, |
| 44 | } |
| 45 | |
| 46 | // initialize the first thread |
| 47 | // this needs to happen before starting the main thread |
| 48 | // since some extensions access environment variables on startup |
| 49 | // the threadIndex on the main thread defaults to 0 -> phpThreads[0].Pin(...) |
| 50 | initialThread := newPHPThread(0) |
| 51 | phpThreads = []*phpThread{initialThread} |
| 52 | |
| 53 | if err := mainThread.start(); err != nil { |
| 54 | return nil, err |
| 55 | } |
| 56 | |
| 57 | // Must follow start(): maxThreads is only final once |
| 58 | // setAutomaticMaxThreads runs on the main PHP thread (before Ready). |
| 59 | C.frankenphp_init_thread_metrics(C.int(mainThread.maxThreads)) |
| 60 | |
| 61 | // initialize all other threads |
| 62 | phpThreads = make([]*phpThread, mainThread.maxThreads) |
| 63 | phpThreads[0] = initialThread |
| 64 | for i := 1; i < mainThread.maxThreads; i++ { |
| 65 | phpThreads[i] = newPHPThread(i) |
| 66 | } |
| 67 | |
| 68 | // start the underlying C threads |
| 69 | var ready sync.WaitGroup |
| 70 | |
| 71 | for i := 0; i < numThreads; i++ { |
| 72 | ready.Go(phpThreads[i].boot) |
| 73 | } |
| 74 | |
| 75 | ready.Wait() |
| 76 | |
| 77 | return mainThread, nil |
| 78 | } |
| 79 | |
| 80 | func drainPHPThreads() { |
| 81 | if mainThread == nil { |