/* This is also exported for teardown after background printing */ void teardown_device_and_mem_for_thread(gx_device *dev, gp_thread_id thread_id, bool bg_print) { gx_device_clist_common *thread_cdev = (gx_device_clist_common *)dev; gx_device_clist_reader *thread_crdev = (gx_device_clist_reader *)dev; gs_memory_t *thread_memory = dev->memory; /* First finish the thread */ gp_thread_finish(thread_id); if (bg_print) { /* we are cleaning up a background printing thread, so we clean up similarly to */ /* what is done by clist_finish_page, but without re-opening the clist files. */ clist_teardown_render_threads(dev); /* we may have used multiple threads */ /* free the thread's icc_table since this was not done by clist_finish_page */ clist_free_icc_table(thread_crdev->icc_table, thread_memory); thread_crdev->icc_table = NULL; /* NB: gdev_prn_free_memory below will free the color_usage_array */ } else { /* make sure this doesn't get freed by gdev_prn_free_memory below */ ((gx_device_clist_reader *)thread_cdev)->color_usage_array = NULL; } rc_decrement(thread_crdev->icc_cache_cl, "teardown_render_thread"); thread_crdev->icc_cache_cl = NULL; /* * Free the BufferSpace, close the band files, optionally unlinking them. * We unlink the files if this call is cleaning up from bg printing. * Note that the BufferSpace is freed using 'ppdev->buf' so the 'data' * pointer doesn't need to be the one that the thread started with */ /* If this thread was being used for background printing and NumRenderingThreads > 0 */ /* the clist_setup_render_threads may have already closed these files */ if (thread_cdev->page_info.cfile != NULL) thread_cdev->page_info.io_procs->fclose(thread_cdev->page_info.bfile, thread_cdev->page_info.bfname, bg_print); if (thread_cdev->page_info.bfile != NULL) thread_cdev->page_info.io_procs->fclose(thread_cdev->page_info.cfile, thread_cdev->page_info.cfname, bg_print); thread_cdev->do_not_open_or_close_bandfiles = true; /* we already closed the files */ gdev_prn_free_memory((gx_device *)thread_cdev); /* Free the device copy this thread used. Note that the deviceN stuff if was allocated and copied earlier for the device will be freed with this call and the icc_struct ref count will be decremented. */ gs_free_object(thread_memory, thread_cdev, "clist_teardown_render_threads"); #ifdef DEBUG dmprintf(thread_memory, "rendering thread ending memory state...\n"); gs_memory_chunk_dump_memory(thread_memory); dmprintf(thread_memory, " memory dump done.\n"); #endif gs_memory_chunk_release(thread_memory); }
void clist_teardown_render_threads(gx_device *dev) { gx_device_clist *cldev = (gx_device_clist *)dev; gx_device_clist_common *cdev = (gx_device_clist_common *)dev; gx_device_clist_reader *crdev = &cldev->reader; gs_memory_t *mem = cdev->bandlist_memory; int i; if (crdev->render_threads != NULL) { /* Wait for each thread to finish then free its memory */ for (i = (crdev->num_render_threads - 1); i >= 0; i--) { clist_render_thread_control_t *thread = &(crdev->render_threads[i]); gx_device_clist_common *thread_cdev = (gx_device_clist_common *)thread->cdev; if (thread->status == RENDER_THREAD_BUSY) gx_semaphore_wait(thread->sema_this); /* Free control semaphores */ gx_semaphore_free(thread->sema_group); gx_semaphore_free(thread->sema_this); /* destroy the thread's buffer device */ thread_cdev->buf_procs.destroy_buf_device(thread->bdev); /* * Free the BufferSpace, close the band files * Note that the BufferSpace is freed using 'ppdev->buf' so the 'data' * pointer doesn't need to be the one that the thread started with */ /* Close the file handles, but don't delete (unlink) the files */ thread_cdev->page_info.io_procs->fclose(thread_cdev->page_bfile, thread_cdev->page_bfname, false); thread_cdev->page_info.io_procs->fclose(thread_cdev->page_cfile, thread_cdev->page_cfname, false); thread_cdev->do_not_open_or_close_bandfiles = true; /* we already closed the files */ gdev_prn_free_memory((gx_device *)thread_cdev); /* Free the device copy this thread used */ gs_free_object(thread->memory, thread_cdev, "clist_teardown_render_threads"); #ifdef DEBUG if (gs_debug[':']) dprintf2("%% Thread %d total usertime=%ld msec\n", i, thread->cputime); dprintf1("\nthread: %d ending memory state...\n", i); gs_memory_chunk_dump_memory(thread->memory); dprintf(" memory dump done.\n"); #endif gs_memory_chunk_release(thread->memory); } cdev->data = crdev->main_thread_data; /* restore the pointer for writing */ gs_free_object(mem, crdev->render_threads, "clist_teardown_render_threads"); crdev->render_threads = NULL; /* Now re-open the clist temp files so we can write to them */ if (cdev->page_cfile == NULL) { char fmode[4]; strcpy(fmode, "a+"); /* file already exists and we want to re-use it */ strncat(fmode, gp_fmode_binary_suffix, 1); cdev->page_info.io_procs->fopen(cdev->page_cfname, fmode, &cdev->page_cfile, mem, cdev->bandlist_memory, true); cdev->page_info.io_procs->fseek(cdev->page_cfile, 0, SEEK_SET, cdev->page_cfname); cdev->page_info.io_procs->fopen(cdev->page_bfname, fmode, &cdev->page_bfile, mem, cdev->bandlist_memory, false); cdev->page_info.io_procs->fseek(cdev->page_bfile, 0, SEEK_SET, cdev->page_bfname); } } }