[sgen] Avoid waiting for workers to report their own finish
If a worker is stuck doing work in another context, it might not be very responsive in transitioning its own state from WORK_ENQUEUED to WORKING and finally to FINISHING. When joining worker threads, we check whether we have any threads working in the corresponding context and, if there aren't any, change their state directly from the gc thread.
We can do this because work is distributed from centralized pools (worker_distribute_gray_queue and the job_queue), instead of per worker. Therefore we don't need all the workers to perform actual work in the context.