// *********************************************************************** // *********************************************************************** // project5 command // // int P5_project5(int argc, char* argv[]) // project 5 { int i; char* new_argv[4]; // child arguments char arg1[16]; char arg2[16]; char arg3[16]; static char* groupReportArgv[] = {"groupReport", "4"}; // check if just changing scheduler mode if (argc > 1) { scheduler_mode = atoi(argv[1]); printf("\nScheduler Mode = %d (%s)", scheduler_mode, scheduler_mode ? "FSS" : "RR"); return 0; } printf("\nStarting Project 5"); for (i = 0; i < NUM_PARENTS; ++i) { num_siblings[i] = (rand() % 25) + 1; printf("\nGroup[%d] = %d", i, num_siblings[i]); } childALive = createSemaphore("childALive", BINARY, 0); parentDead = createSemaphore("parentDead", BINARY, 0); // create parents for (i = 0; i < NUM_PARENTS; i++) { group_count[i] = 0; // zero group counter sprintf(arg1, "parent%d", i + 1); sprintf(arg2, "%d", i + 1); // sprintf(arg3, "%d", 1 + 4 * i); sprintf(arg3, "%d", num_siblings[i]); new_argv[0] = arg1; new_argv[1] = arg2; new_argv[2] = arg3; printf("\nCreate %s with %d child%s", arg1, atoi(arg3), (atoi(arg3) == 1 ? "" : "ren")); createTask(new_argv[0] // task name , parentTask, // parent task MED_PRIORITY, // priority 3, // argc new_argv); // argv SEM_WAIT(parentDead); // wait for parent to die } // create reporting task createTask("Group Report" , // task name groupReportTask, // task MED_PRIORITY, // task priority 2, // task argc groupReportArgv); // task argument pointers return 0; } // end P5_project5
/// <summary> /// Initialize all the semphores to be used /// </summary> void initializeSemaphores() { printf("Inicializando Semaforos... \n"); createSemaphore(CHAIRS_SEM); createSemaphore(BARBERS_SEM); createSemaphore(CASHIER_SEM); createSemaphore(S_CLIENTS_COUNTER_SEM); // Write file header Semaphore *fileSem = createSemaphore(FILE_SEM); sem_wait(fileSem->mutex); writeFile(FILE_HEADER); sem_post(fileSem->mutex); printf("Semaforos creados exitosamente! \n"); }
// ********************************************************************** // ********************************************************************** // create task int createTask(char* name, // task name int (*task)(int, char**), // task address int priority, // task priority int argc, // task argument count char* argv[]) // task argument pointers { int tid; // find an open tcb entry slot for (tid = 0; tid < MAX_TASKS; tid++) { if (tcb[tid].name == 0) { char buf[8]; // create task semaphore if (taskSems[tid]) deleteSemaphore(&taskSems[tid]); sprintf(buf, "task%d", tid); taskSems[tid] = createSemaphore(buf, 0, 0); taskSems[tid]->taskNum = 0; // assign to shell // copy task name tcb[tid].name = (char*)malloc(strlen(name)+1); strcpy(tcb[tid].name, name); // set task address and other parameters tcb[tid].task = task; // task address tcb[tid].state = S_NEW; // NEW task state tcb[tid].priority = priority; // task priority tcb[tid].parent = curTask; // parent tcb[tid].argc = argc; // argument count // ?? malloc new argv parameters tcb[tid].argv = malloc(argc*sizeof(char *)); int i; for (i = 0; i < argc; i++) tcb[tid].argv[i] = argv[i]; // argument pointers tcb[tid].event = 0; // suspend semaphore tcb[tid].RPT = 0; // root page table (project 5) tcb[tid].cdir = CDIR; // inherit parent cDir (project 6) // define task signals createTaskSigHandlers(tid); // Each task must have its own stack and stack pointer. tcb[tid].stack = malloc(STACK_SIZE * sizeof(int)); // ?? may require inserting task into "ready" queue if (tid) swapTask(); // do context switch (if not cli) return tid; // return tcb index (curTask) } } // tcb full! return -1; } // end createTask
void learnProcessSemaphores() { int sem_id = createSemaphore(); /*semaphorePost(sem_id);*/ semaphoreGetCount(sem_id); /*sleep(1000);*/ semaphoreWait(sem_id); semaphoreGetCount(sem_id); }
vk::Move<vk::VkSemaphore> createAndImportSemaphore (const vk::DeviceInterface& vkd, const vk::VkDevice device, vk::VkExternalSemaphoreHandleTypeFlagBitsKHR externalType, NativeHandle& handle, vk::VkSemaphoreImportFlagsKHR flags) { vk::Move<vk::VkSemaphore> semaphore (createSemaphore(vkd, device)); importSemaphore(vkd, device, *semaphore, externalType, handle, flags); return semaphore; }
int main() { int key1=ftok(".",1); int key2=ftok(".",2); int key3=ftok(".",3); printf("%d %d %d",key1,key2,key3); int semid =createSemaphore(key1,2);//S1 S2 int shmid1=createSharedMemory(key2,10);//x printf("shmid1 %d from main\n",shmid1); char *X =(char *)attachSharedMemory(shmid1); // int shmid2=createSharedMemory(key3,10);//y // printf("shmid2 %d from main\n",shmid2); char *Y ; //=//(char *)attachSharedMemory(shmid2); int *values=(int *)malloc(sizeof(int *)*2); *values=0;*(values+1)=0; initSemaphore(semid,values); /* V(semid,0); printf("hi"); P(semid,0); */ int x=0,y=0,i; while(1) { // write(x) i=0; printf("P1 X=%d Y=%d\n",x,y); while(x>0) { *X=x%10-'0';x/=10;X++;i++; } printf("*\n"); *X='\0'; printf("*\n"); X-=i;//X Points to start of shared memory //V(1) V(semid,0); //P(2) P(semid,1); //Read Y i=0; while(*Y!='\0') { y=y*10+(*Y+'0');Y++;i++; } Y-=i; //X=Y+1; x=y+1; printf("P1 X=%d Y=%d\n",x,y); } }
int signalTask(int argc, char* argv[]) { int count = 0; // task variable // create a semaphore Semaphore** mySem = (!strcmp(argv[1], "s1Sem")) ? &s1Sem : &s2Sem; *mySem = createSemaphore(argv[1], 0, 0); // loop waiting for semaphore to be signaled while(count < COUNT_MAX) { SEM_WAIT(*mySem); // wait for signal printf("\n%s Task[%d], count=%d", tcb[curTask].name, curTask, ++count); } return 0; // terminate task } // end signalTask
/** * signalTask */ int signalTask(int argc, char* argv[]) { int count = 0; /* task variable */ TCB* tcb = getTCB(); int curTask = gettid(); // create a semaphore int* mySem = (!strcmp(argv[1], "s1Sem")) ? &s1Sem : &s2Sem; *mySem = createSemaphore(argv[1], 0, 1); // loop waiting for semaphore to be signaled while(count < COUNT_MAX) { semWait(*mySem); printf("%s Task[%d], count=%d\n", tcb[curTask].name, curTask, ++count); } return 0; }
// ********************************************************************** // ********************************************************************** // OS startup // // 1. Init OS // 2. Define reset longjmp vector // 3. Define global system semaphores // 4. Create CLI task // 5. Enter scheduling/idle loop // int main(int argc, char* argv[]) { // save context for restart (a system reset would return here...) int resetCode = setjmp(reset_context); superMode = TRUE; // supervisor mode switch (resetCode) { case POWER_DOWN_QUIT: // quit powerDown(0); printf("\nGoodbye!!"); return 0; case POWER_DOWN_RESTART: // restart powerDown(resetCode); printf("\nRestarting system...\n"); case POWER_UP: // startup break; default: printf("\nShutting down due to error %d", resetCode); powerDown(resetCode); return resetCode; } // output header message printf("%s", STARTUP_MSG); // initalize OS if ( resetCode = initOS()) return resetCode; // create global/system semaphores here //?? vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv charReady = createSemaphore("charReady", BINARY, 0); inBufferReady = createSemaphore("inBufferReady", BINARY, 0); keyboard = createSemaphore("keyboard", BINARY, 1); tics1sec = createSemaphore("tics1sec", BINARY, 0); tics10thsec = createSemaphore("tics10thsec", BINARY, 0); tics10secs = createSemaphore("tics10secs", COUNTING, 0); //?? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // schedule CLI task createTask("myShell", // task name P1_shellTask, // task MED_PRIORITY, // task priority argc, // task arg count argv); // task argument pointers // HERE WE GO................ // Scheduling loop // 1. Check for asynchronous events (character inputs, timers, etc.) // 2. Choose a ready task to schedule // 3. Dispatch task // 4. Loop (forever!) while(1) // scheduling loop { // check for character / timer interrupts pollInterrupts(); // schedule highest priority ready task if ((curTask = scheduler()) < 0) continue; // dispatch curTask, quit OS if negative return if (dispatcher() < 0) break; } // end of scheduling loop // exit os longjmp(reset_context, POWER_DOWN_QUIT); return 0; } // end main
void createSemMethod(char buffer1[]){ theTickets = createSemaphore("theTickets", COUNTING, MAX_TICKETS); SWAP; passengerRide = createSemaphore("passengerRide", BINARY, 0); sellDriverTick = createSemaphore("sellDriverTick", BINARY, 0); helloDriverWakeUp = createSemaphore("helloDriverWakeUp", BINARY, 0); passengerJumpIntoRide = createSemaphore("passengerJumpIntoRide", BINARY, 0); ready2GoDriver = createSemaphore("ready2GoDriver", BINARY, 0); driverCar = createSemaphore("driverCar", BINARY, 0); noDriverYet = createSemaphore("noDriverYet", BINARY, 0); parkEntry = createSemaphore("parkEntry ", COUNTING, 20); ticketSold = createSemaphore("ticketSold", BINARY, 0); buyTicketMutex = createSemaphore("buyTicketMutex", BINARY, 1); rideFinished = createSemaphore("rideFinished", BINARY, 0); dinosaur = createSemaphore("dinosaur", BINARY, 1); visitMuseum = createSemaphore("visitMuseum", COUNTING, MAX_IN_MUSEUM); visitGiftShop = createSemaphore("visitGiftShop", COUNTING, MAX_IN_GIFTSHOP); buyGiftMutex = createSemaphore("buyGiftMutex", BINARY, 1); driverSellGift = createSemaphore("driverSellGift", BINARY, 0); giftSold = createSemaphore("gift sold by driver", BINARY, 0); finishingUp = createSemaphore("finishing up", BINARY, 0); int i = 0; while(i < NUM_DRIVERS){ sprintf(buffer1, "driver done driving %d", i); driverFinished[i] = createSemaphore(buffer1, BINARY, 0); i++; } }
void createSwapChainAndImages(VulkanContext& context, VulkanSurfaceContext& surfaceContext) { // Pick an image count and format. According to section 30.5 of VK 1.1, maxImageCount of zero // apparently means "that there is no limit on the number of images, though there may be limits // related to the total amount of memory used by presentable images." uint32_t desiredImageCount = 2; const uint32_t maxImageCount = surfaceContext.surfaceCapabilities.maxImageCount; if (desiredImageCount < surfaceContext.surfaceCapabilities.minImageCount || (maxImageCount != 0 && desiredImageCount > maxImageCount)) { utils::slog.e << "Swap chain does not support " << desiredImageCount << " images.\n"; desiredImageCount = surfaceContext.surfaceCapabilities.minImageCount; } surfaceContext.surfaceFormat = surfaceContext.surfaceFormats[0]; for (const VkSurfaceFormatKHR& format : surfaceContext.surfaceFormats) { if (format.format == VK_FORMAT_R8G8B8A8_UNORM) { surfaceContext.surfaceFormat = format; break; } } const auto compositionCaps = surfaceContext.surfaceCapabilities.supportedCompositeAlpha; const auto compositeAlpha = (compositionCaps & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // Create the low-level swap chain. const auto size = surfaceContext.surfaceCapabilities.currentExtent; VkSwapchainCreateInfoKHR createInfo { .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .surface = surfaceContext.surface, .minImageCount = desiredImageCount, .imageFormat = surfaceContext.surfaceFormat.format, .imageColorSpace = surfaceContext.surfaceFormat.colorSpace, .imageExtent = size, .imageArrayLayers = 1, .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, .compositeAlpha = compositeAlpha, .presentMode = VK_PRESENT_MODE_FIFO_KHR, .clipped = VK_TRUE }; VkSwapchainKHR swapchain; VkResult result = vkCreateSwapchainKHR(context.device, &createInfo, VKALLOC, &swapchain); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkGetPhysicalDeviceSurfaceFormatsKHR error."); surfaceContext.swapchain = swapchain; // Extract the VkImage handles from the swap chain. uint32_t imageCount; result = vkGetSwapchainImagesKHR(context.device, swapchain, &imageCount, nullptr); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkGetSwapchainImagesKHR count error."); surfaceContext.swapContexts.resize(imageCount); std::vector<VkImage> images(imageCount); result = vkGetSwapchainImagesKHR(context.device, swapchain, &imageCount, images.data()); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkGetSwapchainImagesKHR error."); for (size_t i = 0; i < images.size(); ++i) { surfaceContext.swapContexts[i].attachment = { .image = images[i], .format = surfaceContext.surfaceFormat.format }; } utils::slog.i << "vkCreateSwapchain" << ": " << size.width << "x" << size.height << ", " << surfaceContext.surfaceFormat.format << ", " << surfaceContext.surfaceFormat.colorSpace << ", " << imageCount << utils::io::endl; // Create image views. VkImageViewCreateInfo ivCreateInfo = {}; ivCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; ivCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; ivCreateInfo.format = surfaceContext.surfaceFormat.format; ivCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; ivCreateInfo.subresourceRange.levelCount = 1; ivCreateInfo.subresourceRange.layerCount = 1; for (size_t i = 0; i < images.size(); ++i) { ivCreateInfo.image = images[i]; result = vkCreateImageView(context.device, &ivCreateInfo, VKALLOC, &surfaceContext.swapContexts[i].attachment.view); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateImageView error."); } createSemaphore(context.device, &surfaceContext.imageAvailable); createSemaphore(context.device, &surfaceContext.renderingFinished); surfaceContext.depth = {}; } void createDepthBuffer(VulkanContext& context, VulkanSurfaceContext& surfaceContext, VkFormat depthFormat) { assert(context.cmdbuffer); // Create an appropriately-sized device-only VkImage. const auto size = surfaceContext.surfaceCapabilities.currentExtent; VkImage depthImage; VkImageCreateInfo imageInfo { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .imageType = VK_IMAGE_TYPE_2D, .extent = { size.width, size.height, 1 }, .format = depthFormat, .mipLevels = 1, .arrayLayers = 1, .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, .samples = VK_SAMPLE_COUNT_1_BIT, }; VkResult error = vkCreateImage(context.device, &imageInfo, VKALLOC, &depthImage); ASSERT_POSTCONDITION(!error, "Unable to create depth image."); // Allocate memory for the VkImage and bind it. VkMemoryRequirements memReqs; vkGetImageMemoryRequirements(context.device, depthImage, &memReqs); VkMemoryAllocateInfo allocInfo { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .allocationSize = memReqs.size, .memoryTypeIndex = selectMemoryType(context, memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) }; error = vkAllocateMemory(context.device, &allocInfo, nullptr, &surfaceContext.depth.memory); ASSERT_POSTCONDITION(!error, "Unable to allocate depth memory."); error = vkBindImageMemory(context.device, depthImage, surfaceContext.depth.memory, 0); ASSERT_POSTCONDITION(!error, "Unable to bind depth memory."); // Create a VkImageView so that we can attach depth to the framebuffer. VkImageView depthView; VkImageViewCreateInfo viewInfo { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .image = depthImage, .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = depthFormat, .subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, .subresourceRange.levelCount = 1, .subresourceRange.layerCount = 1, }; error = vkCreateImageView(context.device, &viewInfo, VKALLOC, &depthView); ASSERT_POSTCONDITION(!error, "Unable to create depth view."); // Transition the depth image into an optimal layout. VkImageMemoryBarrier barrier { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = depthImage, .subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, .subresourceRange.levelCount = 1, .subresourceRange.layerCount = 1, .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT }; vkCmdPipelineBarrier(context.cmdbuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); // Go ahead and set the depth attachment fields, which serves as a signal to VulkanDriver that // it is now ready. surfaceContext.depth.view = depthView; surfaceContext.depth.image = depthImage; surfaceContext.depth.format = depthFormat; } void transitionDepthBuffer(VulkanContext& context, VulkanSurfaceContext& sc, VkFormat depthFormat) { // Begin a new command buffer solely for the purpose of transitioning the image layout. SwapContext& swap = getSwapContext(context); VkResult result = vkWaitForFences(context.device, 1, &swap.fence, VK_FALSE, UINT64_MAX); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkWaitForFences error."); result = vkResetFences(context.device, 1, &swap.fence); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkResetFences error."); VkCommandBuffer cmdbuffer = swap.cmdbuffer; result = vkResetCommandBuffer(cmdbuffer, 0); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkResetCommandBuffer error."); VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, }; result = vkBeginCommandBuffer(cmdbuffer, &beginInfo); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkBeginCommandBuffer error."); context.cmdbuffer = cmdbuffer; // Create the depth buffer and issue a pipeline barrier command. createDepthBuffer(context, sc, depthFormat); // Flush the command buffer. result = vkEndCommandBuffer(context.cmdbuffer); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkEndCommandBuffer error."); context.cmdbuffer = nullptr; VkSubmitInfo submitInfo { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = 1, .pCommandBuffers = &swap.cmdbuffer, }; result = vkQueueSubmit(context.graphicsQueue, 1, &submitInfo, swap.fence); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkQueueSubmit error."); swap.submitted = false; } void createCommandBuffersAndFences(VulkanContext& context, VulkanSurfaceContext& surfaceContext) { // Allocate command buffers. VkCommandBufferAllocateInfo allocateInfo = {}; allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocateInfo.commandPool = context.commandPool; allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocateInfo.commandBufferCount = (uint32_t) surfaceContext.swapContexts.size(); std::vector<VkCommandBuffer> cmdbufs(allocateInfo.commandBufferCount); VkResult result = vkAllocateCommandBuffers(context.device, &allocateInfo, cmdbufs.data()); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkAllocateCommandBuffers error."); for (uint32_t i = 0; i < allocateInfo.commandBufferCount; ++i) { surfaceContext.swapContexts[i].cmdbuffer = cmdbufs[i]; } // Create fences. VkFenceCreateInfo fenceCreateInfo = {}; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (uint32_t i = 0; i < allocateInfo.commandBufferCount; i++) { result = vkCreateFence(context.device, &fenceCreateInfo, VKALLOC, &surfaceContext.swapContexts[i].fence); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateFence error."); } } void destroySurfaceContext(VulkanContext& context, VulkanSurfaceContext& surfaceContext) { for (SwapContext& swapContext : surfaceContext.swapContexts) { vkFreeCommandBuffers(context.device, context.commandPool, 1, &swapContext.cmdbuffer); vkDestroyFence(context.device, swapContext.fence, VKALLOC); vkDestroyImageView(context.device, swapContext.attachment.view, VKALLOC); swapContext.fence = VK_NULL_HANDLE; swapContext.attachment.view = VK_NULL_HANDLE; } vkDestroySwapchainKHR(context.device, surfaceContext.swapchain, VKALLOC); vkDestroySemaphore(context.device, surfaceContext.imageAvailable, VKALLOC); vkDestroySemaphore(context.device, surfaceContext.renderingFinished, VKALLOC); vkDestroySurfaceKHR(context.instance, surfaceContext.surface, VKALLOC); vkDestroyImageView(context.device, surfaceContext.depth.view, VKALLOC); vkDestroyImage(context.device, surfaceContext.depth.image, VKALLOC); vkFreeMemory(context.device, surfaceContext.depth.memory, VKALLOC); if (context.currentSurface == &surfaceContext) { context.currentSurface = nullptr; } } uint32_t selectMemoryType(VulkanContext& context, uint32_t flags, VkFlags reqs) { for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) { if (flags & 1) { if ((context.memoryProperties.memoryTypes[i].propertyFlags & reqs) == reqs) { return i; } } flags >>= 1; } ASSERT_POSTCONDITION(false, "Unable to find a memory type that meets requirements."); return (uint32_t) ~0ul; } VkFormat getVkFormat(ElementType type, bool normalized) { using ElementType = ElementType; if (normalized) { switch (type) { // Single Component Types case ElementType::BYTE: return VK_FORMAT_R8_SNORM; case ElementType::UBYTE: return VK_FORMAT_R8_UNORM; case ElementType::SHORT: return VK_FORMAT_R16_SNORM; case ElementType::USHORT: return VK_FORMAT_R16_UNORM; // Two Component Types case ElementType::BYTE2: return VK_FORMAT_R8G8_SNORM; case ElementType::UBYTE2: return VK_FORMAT_R8G8_UNORM; case ElementType::SHORT2: return VK_FORMAT_R16G16_SNORM; case ElementType::USHORT2: return VK_FORMAT_R16G16_UNORM; // Three Component Types case ElementType::BYTE3: return VK_FORMAT_R8G8B8_SNORM; case ElementType::UBYTE3: return VK_FORMAT_R8G8B8_UNORM; case ElementType::SHORT3: return VK_FORMAT_R16G16B16_SNORM; case ElementType::USHORT3: return VK_FORMAT_R16G16B16_UNORM; // Four Component Types case ElementType::BYTE4: return VK_FORMAT_R8G8B8A8_SNORM; case ElementType::UBYTE4: return VK_FORMAT_R8G8B8A8_UNORM; case ElementType::SHORT4: return VK_FORMAT_R16G16B16A16_SNORM; case ElementType::USHORT4: return VK_FORMAT_R16G16B16A16_UNORM; default: ASSERT_POSTCONDITION(false, "Normalized format does not exist."); return VK_FORMAT_UNDEFINED; } } switch (type) { // Single Component Types case ElementType::BYTE: return VK_FORMAT_R8_SINT; case ElementType::UBYTE: return VK_FORMAT_R8_UINT; case ElementType::SHORT: return VK_FORMAT_R16_SINT; case ElementType::USHORT: return VK_FORMAT_R16_UINT; case ElementType::HALF: return VK_FORMAT_R16_SFLOAT; case ElementType::INT: return VK_FORMAT_R32_SINT; case ElementType::UINT: return VK_FORMAT_R32_UINT; case ElementType::FLOAT: return VK_FORMAT_R32_SFLOAT; // Two Component Types case ElementType::BYTE2: return VK_FORMAT_R8G8_SINT; case ElementType::UBYTE2: return VK_FORMAT_R8G8_UINT; case ElementType::SHORT2: return VK_FORMAT_R16G16_SINT; case ElementType::USHORT2: return VK_FORMAT_R16G16_UINT; case ElementType::HALF2: return VK_FORMAT_R16G16_SFLOAT; case ElementType::FLOAT2: return VK_FORMAT_R32G32_SFLOAT; // Three Component Types case ElementType::BYTE3: return VK_FORMAT_R8G8B8_SINT; case ElementType::UBYTE3: return VK_FORMAT_R8G8B8_UINT; case ElementType::SHORT3: return VK_FORMAT_R16G16B16_SINT; case ElementType::USHORT3: return VK_FORMAT_R16G16B16_UINT; case ElementType::HALF3: return VK_FORMAT_R16G16B16_SFLOAT; case ElementType::FLOAT3: return VK_FORMAT_R32G32B32_SFLOAT; // Four Component Types case ElementType::BYTE4: return VK_FORMAT_R8G8B8A8_SINT; case ElementType::UBYTE4: return VK_FORMAT_R8G8B8A8_UINT; case ElementType::SHORT4: return VK_FORMAT_R16G16B16A16_SINT; case ElementType::USHORT4: return VK_FORMAT_R16G16B16A16_UINT; case ElementType::HALF4: return VK_FORMAT_R16G16B16A16_SFLOAT; case ElementType::FLOAT4: return VK_FORMAT_R32G32B32A32_SFLOAT; } return VK_FORMAT_UNDEFINED; } VkFormat getVkFormat(TextureFormat format) { using TextureFormat = TextureFormat; switch (format) { // 8 bits per element. case TextureFormat::R8: return VK_FORMAT_R8_UNORM; case TextureFormat::R8_SNORM: return VK_FORMAT_R8_SNORM; case TextureFormat::R8UI: return VK_FORMAT_R8_UINT; case TextureFormat::R8I: return VK_FORMAT_R8_SINT; case TextureFormat::STENCIL8: return VK_FORMAT_S8_UINT; // 16 bits per element. case TextureFormat::R16F: return VK_FORMAT_R16_SFLOAT; case TextureFormat::R16UI: return VK_FORMAT_R16_UINT; case TextureFormat::R16I: return VK_FORMAT_R16_SINT; case TextureFormat::RG8: return VK_FORMAT_R8G8_UNORM; case TextureFormat::RG8_SNORM: return VK_FORMAT_R8G8_SNORM; case TextureFormat::RG8UI: return VK_FORMAT_R8G8_UINT; case TextureFormat::RG8I: return VK_FORMAT_R8G8_SINT; case TextureFormat::RGB565: return VK_FORMAT_R5G6B5_UNORM_PACK16; case TextureFormat::RGB5_A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16; case TextureFormat::RGBA4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16; case TextureFormat::DEPTH16: return VK_FORMAT_D16_UNORM; // 24 bits per element. In practice, very few GPU vendors support these. For simplicity // we just assume they are not supported, not bothering to query the device capabilities. // Note that VK_FORMAT_ enums for 24-bit formats exist, but are meant for vertex attributes. case TextureFormat::RGB8: case TextureFormat::SRGB8: case TextureFormat::RGB8_SNORM: case TextureFormat::RGB8UI: case TextureFormat::RGB8I: case TextureFormat::DEPTH24: return VK_FORMAT_UNDEFINED; // 32 bits per element. case TextureFormat::R32F: return VK_FORMAT_R32_SFLOAT; case TextureFormat::R32UI: return VK_FORMAT_R32_UINT; case TextureFormat::R32I: return VK_FORMAT_R32_SINT; case TextureFormat::RG16F: return VK_FORMAT_R16G16_SFLOAT; case TextureFormat::RG16UI: return VK_FORMAT_R16G16_UINT; case TextureFormat::RG16I: return VK_FORMAT_R16G16_SINT; case TextureFormat::R11F_G11F_B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; case TextureFormat::RGB9_E5: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; case TextureFormat::RGBA8: return VK_FORMAT_R8G8B8A8_UNORM; case TextureFormat::SRGB8_A8: return VK_FORMAT_R8G8B8A8_SRGB; case TextureFormat::RGBA8_SNORM: return VK_FORMAT_R8G8B8A8_SNORM; case TextureFormat::RGBM: return VK_FORMAT_R8G8B8A8_UNORM; case TextureFormat::RGB10_A2: return VK_FORMAT_A2R10G10B10_UNORM_PACK32; case TextureFormat::RGBA8UI: return VK_FORMAT_R8G8B8A8_UINT; case TextureFormat::RGBA8I: return VK_FORMAT_R8G8B8A8_SINT; case TextureFormat::DEPTH32F: return VK_FORMAT_D32_SFLOAT; case TextureFormat::DEPTH24_STENCIL8: return VK_FORMAT_D24_UNORM_S8_UINT; case TextureFormat::DEPTH32F_STENCIL8: return VK_FORMAT_D32_SFLOAT_S8_UINT; // 48 bits per element. Note that many GPU vendors do not support these. case TextureFormat::RGB16F: return VK_FORMAT_R16G16B16_SFLOAT; case TextureFormat::RGB16UI: return VK_FORMAT_R16G16B16_UINT; case TextureFormat::RGB16I: return VK_FORMAT_R16G16B16_SINT; // 64 bits per element. case TextureFormat::RG32F: return VK_FORMAT_R32G32_SFLOAT; case TextureFormat::RG32UI: return VK_FORMAT_R32G32_UINT; case TextureFormat::RG32I: return VK_FORMAT_R32G32_SINT; case TextureFormat::RGBA16F: return VK_FORMAT_R16G16B16A16_SFLOAT; case TextureFormat::RGBA16UI: return VK_FORMAT_R16G16B16A16_UINT; case TextureFormat::RGBA16I: return VK_FORMAT_R16G16B16A16_SINT; // 96-bits per element. case TextureFormat::RGB32F: return VK_FORMAT_R32G32B32_SFLOAT; case TextureFormat::RGB32UI: return VK_FORMAT_R32G32B32_UINT; case TextureFormat::RGB32I: return VK_FORMAT_R32G32B32_SINT; // 128-bits per element case TextureFormat::RGBA32F: return VK_FORMAT_R32G32B32A32_SFLOAT; case TextureFormat::RGBA32UI: return VK_FORMAT_R32G32B32A32_UINT; case TextureFormat::RGBA32I: return VK_FORMAT_R32G32B32A32_SINT; default: return VK_FORMAT_UNDEFINED; } } uint32_t getBytesPerPixel(TextureFormat format) { return details::FTexture::getFormatSize(format); } // See also FTexture::computeTextureDataSize, which takes a public-facing Texture format rather // than a driver-level Texture format, and can account for a specified byte alignment. uint32_t computeSize(TextureFormat format, uint32_t w, uint32_t h, uint32_t d) { const size_t bytesPerTexel = details::FTexture::getFormatSize(format); return bytesPerTexel * w * h * d; } SwapContext& getSwapContext(VulkanContext& context) { VulkanSurfaceContext& surface = *context.currentSurface; return surface.swapContexts[surface.currentSwapIndex]; } bool hasPendingWork(VulkanContext& context) { if (context.pendingWork.size() > 0) { return true; } if (context.currentSurface) { for (auto& swapContext : context.currentSurface->swapContexts) { if (swapContext.pendingWork.size() > 0) { return true; } } } return false; } VkCompareOp getCompareOp(SamplerCompareFunc func) { using Compare = driver::SamplerCompareFunc; switch (func) { case Compare::LE: return VK_COMPARE_OP_LESS_OR_EQUAL; case Compare::GE: return VK_COMPARE_OP_GREATER_OR_EQUAL; case Compare::L: return VK_COMPARE_OP_LESS; case Compare::G: return VK_COMPARE_OP_GREATER; case Compare::E: return VK_COMPARE_OP_EQUAL; case Compare::NE: return VK_COMPARE_OP_NOT_EQUAL; case Compare::A: return VK_COMPARE_OP_ALWAYS; case Compare::N: return VK_COMPARE_OP_NEVER; } } VkBlendFactor getBlendFactor(BlendFunction mode) { using BlendFunction = filament::driver::BlendFunction; switch (mode) { case BlendFunction::ZERO: return VK_BLEND_FACTOR_ZERO; case BlendFunction::ONE: return VK_BLEND_FACTOR_ONE; case BlendFunction::SRC_COLOR: return VK_BLEND_FACTOR_SRC_COLOR; case BlendFunction::ONE_MINUS_SRC_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; case BlendFunction::DST_COLOR: return VK_BLEND_FACTOR_DST_COLOR; case BlendFunction::ONE_MINUS_DST_COLOR: return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; case BlendFunction::SRC_ALPHA: return VK_BLEND_FACTOR_SRC_ALPHA; case BlendFunction::ONE_MINUS_SRC_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; case BlendFunction::DST_ALPHA: return VK_BLEND_FACTOR_DST_ALPHA; case BlendFunction::ONE_MINUS_DST_ALPHA: return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; case BlendFunction::SRC_ALPHA_SATURATE: return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE; } } void waitForIdle(VulkanContext& context) { // If there's no valid GPU then we have nothing to do. if (!context.device) { return; } // If there's no surface, then there's no command buffer. if (!context.currentSurface) { return; } // First, wait for submitted command buffer(s) to finish. VkFence fences[2]; uint32_t nfences = 0; auto& surfaceContext = *context.currentSurface; for (auto& swapContext : surfaceContext.swapContexts) { assert(nfences < 2); if (swapContext.submitted && swapContext.fence) { fences[nfences++] = swapContext.fence; swapContext.submitted = false; } } if (nfences > 0) { vkWaitForFences(context.device, nfences, fences, VK_FALSE, ~0ull); } // If we don't have any pending work, we're done. if (!hasPendingWork(context)) { return; } // We cannot invoke arbitrary commands inside a render pass. assert(context.currentRenderPass.renderPass == VK_NULL_HANDLE); // Create a one-off command buffer to avoid the cost of swap chain acquisition and to avoid // the possibility of SURFACE_LOST. Note that Vulkan command buffers use the Allocate/Free // model instead of Create/Destroy and are therefore okay to create at a high frequency. VkCommandBuffer cmdbuffer; VkFence fence; VkCommandBufferBeginInfo beginInfo { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VkCommandBufferAllocateInfo allocateInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .commandPool = context.commandPool, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1 }; VkFenceCreateInfo fenceCreateInfo { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, }; vkAllocateCommandBuffers(context.device, &allocateInfo, &cmdbuffer); vkCreateFence(context.device, &fenceCreateInfo, VKALLOC, &fence); // Keep performing work until there's nothing queued up. This should never iterate more than // a couple times because the only work we queue up is for resource transition / reclamation. VkPipelineStageFlags waitDestStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; VkSubmitInfo submitInfo { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pWaitDstStageMask = &waitDestStageMask, .commandBufferCount = 1, .pCommandBuffers = &cmdbuffer, }; int cycles = 0; while (hasPendingWork(context)) { if (cycles++ > 2) { utils::slog.e << "Unexpected daisychaining of pending work." << utils::io::endl; break; } for (auto& swapContext : context.currentSurface->swapContexts) { vkBeginCommandBuffer(cmdbuffer, &beginInfo); performPendingWork(context, swapContext, cmdbuffer); vkEndCommandBuffer(cmdbuffer); vkQueueSubmit(context.graphicsQueue, 1, &submitInfo, fence); vkWaitForFences(context.device, 1, &fence, VK_FALSE, UINT64_MAX); vkResetFences(context.device, 1, &fence); vkResetCommandBuffer(cmdbuffer, 0); } } vkFreeCommandBuffers(context.device, context.commandPool, 1, &cmdbuffer); vkDestroyFence(context.device, fence, VKALLOC); } void acquireCommandBuffer(VulkanContext& context) { // Ask Vulkan for the next image in the swap chain and update the currentSwapIndex. VulkanSurfaceContext& surface = *context.currentSurface; VkResult result = vkAcquireNextImageKHR(context.device, surface.swapchain, UINT64_MAX, surface.imageAvailable, VK_NULL_HANDLE, &surface.currentSwapIndex); ASSERT_POSTCONDITION(result != VK_ERROR_OUT_OF_DATE_KHR, "Stale / resized swap chain not yet supported."); ASSERT_POSTCONDITION(result == VK_SUBOPTIMAL_KHR || result == VK_SUCCESS, "vkAcquireNextImageKHR error."); SwapContext& swap = getSwapContext(context); // Ensure that the previous submission of this command buffer has finished. result = vkWaitForFences(context.device, 1, &swap.fence, VK_FALSE, UINT64_MAX); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkWaitForFences error."); // Restart the command buffer. result = vkResetFences(context.device, 1, &swap.fence); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkResetFences error."); VkCommandBuffer cmdbuffer = swap.cmdbuffer; VkResult error = vkResetCommandBuffer(cmdbuffer, 0); ASSERT_POSTCONDITION(not error, "vkResetCommandBuffer error."); VkCommandBufferBeginInfo beginInfo { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, }; error = vkBeginCommandBuffer(cmdbuffer, &beginInfo); ASSERT_POSTCONDITION(not error, "vkBeginCommandBuffer error."); context.cmdbuffer = cmdbuffer; swap.submitted = false; } void releaseCommandBuffer(VulkanContext& context) { // Finalize the command buffer and set the cmdbuffer pointer to null. VkResult result = vkEndCommandBuffer(context.cmdbuffer); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkEndCommandBuffer error."); context.cmdbuffer = nullptr; // Submit the command buffer. VkPipelineStageFlags waitDestStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; VulkanSurfaceContext& surfaceContext = *context.currentSurface; SwapContext& swapContext = getSwapContext(context); VkSubmitInfo submitInfo { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .waitSemaphoreCount = 1u, .pWaitSemaphores = &surfaceContext.imageAvailable, .pWaitDstStageMask = &waitDestStageMask, .commandBufferCount = 1, .pCommandBuffers = &swapContext.cmdbuffer, .signalSemaphoreCount = 1u, .pSignalSemaphores = &surfaceContext.renderingFinished, }; result = vkQueueSubmit(context.graphicsQueue, 1, &submitInfo, swapContext.fence); ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkQueueSubmit error."); swapContext.submitted = true; } void performPendingWork(VulkanContext& context, SwapContext& swapContext, VkCommandBuffer cmdbuf) { // First, execute pending tasks that are specific to this swap context. Copy the tasks into a // local queue first, which allows newly added tasks to be deferred until the next frame. decltype(swapContext.pendingWork) tasks; tasks.swap(swapContext.pendingWork); for (auto& callback : tasks) { callback(cmdbuf); } // Next, execute the global pending work. Again, we copy the work queue into a local queue // to allow tasks to re-add themselves. tasks.clear(); tasks.swap(context.pendingWork); for (auto& callback : tasks) { callback(cmdbuf); } } // Flushes the command buffer and waits for it to finish executing. Useful for diagnosing // sychronization issues. void flushCommandBuffer(VulkanContext& context) { VulkanSurfaceContext& surface = *context.currentSurface; const SwapContext& sc = surface.swapContexts[surface.currentSwapIndex]; // Submit the command buffer. VkResult error = vkEndCommandBuffer(context.cmdbuffer); ASSERT_POSTCONDITION(!error, "vkEndCommandBuffer error."); VkPipelineStageFlags waitDestStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; VkSubmitInfo submitInfo { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pWaitDstStageMask = &waitDestStageMask, .commandBufferCount = 1, .pCommandBuffers = &context.cmdbuffer, }; error = vkQueueSubmit(context.graphicsQueue, 1, &submitInfo, sc.fence); ASSERT_POSTCONDITION(!error, "vkQueueSubmit error."); // Restart the command buffer. error = vkWaitForFences(context.device, 1, &sc.fence, VK_FALSE, UINT64_MAX); ASSERT_POSTCONDITION(!error, "vkWaitForFences error."); error = vkResetFences(context.device, 1, &sc.fence); ASSERT_POSTCONDITION(!error, "vkResetFences error."); error = vkResetCommandBuffer(context.cmdbuffer, 0); ASSERT_POSTCONDITION(!error, "vkResetCommandBuffer error."); VkCommandBufferBeginInfo beginInfo { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, }; error = vkBeginCommandBuffer(context.cmdbuffer, &beginInfo); ASSERT_POSTCONDITION(!error, "vkBeginCommandBuffer error."); } VkFormat findSupportedFormat(VulkanContext& context, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { for (VkFormat format : candidates) { VkFormatProperties props; vkGetPhysicalDeviceFormatProperties(context.physicalDevice, format, &props); if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { return format; } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { return format; } } return VK_FORMAT_UNDEFINED; } } // namespace filament } // namespace driver
/* * Create a semaphore. * Params: * state->ebx - user address of name of semaphore * state->ecx - length of semaphore name * state->edx - initial semaphore count * Returns: the global semaphore id */ static int Sys_CreateSemaphore(struct Interrupt_State* state) { return createSemaphore(state->ebx, state->ecx, state->edx); }
// ********************************************************************** // ********************************************************************** // create task int createTask(char* name, // task name int (*task)(int, char**), // task address int priority, // task priority int argc, // task argument count char* argv[]) // task argument pointers { int tid; // find an open tcb entry slot for (tid = 0; tid < MAX_TASKS; tid++) { if (tcb[tid].name == 0) { char buf[8]; // create task semaphore if (taskSems[tid]) deleteSemaphore(&taskSems[tid]); sprintf(buf, "task%d", tid); taskSems[tid] = createSemaphore(buf, 0, 0); taskSems[tid]->taskNum = 0; // assign to shell // copy task name tcb[tid].name = (char*)malloc(strlen(name)+1); strcpy(tcb[tid].name, name); // set task address and other parameters tcb[tid].taskTime = 0; // SCOTT - p5 tcb[tid].task = task; // task address tcb[tid].state = S_NEW; // NEW task state tcb[tid].priority = priority; // task priority tcb[tid].parent = curTask; // parent tcb[tid].argc = argc; // argument count // SCOTT malloc new argv parameters char** mallocdArgv = malloc(sizeof(char*) * MAX_ARGS); int i; for (i = 0; i < argc; i++) { mallocdArgv[i] = malloc(sizeof(char) * MAX_ARG_LENGTH); // max arg length = 50 strcpy(mallocdArgv[i], argv[i]); } tcb[tid].argv = mallocdArgv; // argument pointers // change this line // end malloc SCOTT tcb[tid].event = 0; // suspend semaphore // SCOTT - set RPT //tcb[tid].RPT = 0; // root page table (project 5) 4?? tcb[tid].RPT = LC3_RPT + ((tid) ? ((tid - 1) << 6) : 0); // from slide 35 tcb[tid].cdir = CDIR; // inherit parent cDir (project 6) // define task signals createTaskSigHandlers(tid); // Each task must have its own stack and stack pointer. tcb[tid].stack = malloc(STACK_SIZE * sizeof(int)); // ?? may require inserting task into "ready" queue enqueue(readyQueue, tid, tcb[tid].priority); // SCOTT if (tid) swapTask(); // do context switch (if not cli) return tid; // return tcb index (curTask) } } // tcb full! return -1; } // end createTask
// ********************************************************************** // ********************************************************************** // create task int createTask(char* name, // task name int (*task)(int, char**), // task address int priority, // task priority int argc, // task argument count char* argv[]) // task argument pointers { int tid; // find an open tcb entry slot for (tid = 0; tid < MAX_TASKS; tid++) { if (tcb[tid].name == 0) { int i = 0; char** newArgv = malloc(argc * sizeof(char*)); for(i = 0; i < argc; i++) { newArgv[i] = malloc(sizeof(char) * (strlen(argv[i]) + 1)); strcpy(newArgv[i], argv[i]); } char buf[8]; // create task semaphore if (taskSems[tid]) deleteSemaphore(&taskSems[tid]); sprintf(buf, "task%d", tid); taskSems[tid] = createSemaphore(buf, 0, 0); taskSems[tid]->taskNum = 0; // assign to shell // copy task name tcb[tid].name = (char*)malloc(strlen(name)+1); strcpy(tcb[tid].name, name); // set task address and other parameters tcb[tid].task = task; // task address tcb[tid].state = S_NEW; // NEW task state tcb[tid].priority = priority; // task priority tcb[tid].time = 0; // time tcb[tid].parent = curTask; // parent //printf("\nCurTask: %d, Name: %s", curTask, tcb[curTask].name); //printf("\nNewTask: %d, Name: %s", tid, tcb[tid].name); tcb[tid].argc = argc; // argument count // ?? malloc new argv parameters tcb[tid].argv = newArgv; // argument pointers tcb[tid].event = 0; // suspend semaphore tcb[tid].RPT = 0x2440;//(tid - 1) * 64 + 0x2400; // root page table (project 5) tcb[tid].cdir = CDIR; // inherit parent cDir (project 6) // signals tcb[tid].signal = 0; if (tid) { // inherit parent signal handlers tcb[tid].sigContHandler = tcb[curTask].sigContHandler; // task mySIGCONT handler tcb[tid].sigIntHandler = tcb[curTask].sigIntHandler; // mySIGINT handler tcb[tid].sigTermHandler = tcb[curTask].sigTermHandler; // task mySIGTERM handler tcb[tid].sigTstpHandler = tcb[curTask].sigTstpHandler; // task mySIGTSTP handler } else { // otherwise use defaults tcb[tid].sigContHandler = defaultSigContHandler; // task mySIGINT handler tcb[tid].sigIntHandler = defaultSigIntHandler; // task mySIGINT handler tcb[tid].sigTermHandler = defaultSigTermHandler; // task mySIGINT handler tcb[tid].sigTstpHandler = defaultSigTstpHandler; // task mySIGINT handler } // Each task must have its own stack and stack pointer. tcb[tid].stack = malloc(STACK_SIZE * sizeof(int)); // ?? may require inserting task into "ready" queue enqueue(tid, &READY_QUEUE); if (tid) swapTask(); // do context switch (if not cli) return tid; // return tcb index (curTask) } } // tcb full! return -1; } // end createTask
// ********************************************************************** // ********************************************************************** // OS startup // // 1. Init OS // 2. Define reset longjmp vector // 3. Define global system semaphores // 4. Create CLI task // 5. Enter scheduling/idle loop // int main(int argc, char* argv[]) { // All the 'powerDown' invocations must occur in the 'main' // context in order to facilitate 'killTask'. 'killTask' must // free any stack memory associated with current known tasks. As // such, the stack context must be one not associated with a task. // The proper method is to longjmp to the 'reset_context' that // restores the stack for 'main' and then invoke the 'powerDown' // sequence. // save context for restart (a system reset would return here...) int resetCode = setjmp(reset_context); superMode = TRUE; // supervisor mode switch (resetCode) { case POWER_DOWN_QUIT: // quit powerDown(0); printf("\nGoodbye!!"); return 0; case POWER_DOWN_RESTART: // restart powerDown(resetCode); printf("\nRestarting system...\n"); break; case POWER_UP: // startup break; default: printf("\nShutting down due to error %d", resetCode); powerDown(resetCode); return 0; } // output header message printf("%s", STARTUP_MSG); // initalize OS initOS(); // create global/system semaphores here //?? vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv charReady = createSemaphore("charReady", BINARY, 0); inBufferReady = createSemaphore("inBufferReady", BINARY, 0); keyboard = createSemaphore("keyboard", BINARY, 1); tics1sec = createSemaphore("tics1sec", COUNTING, 0); tics10thsec = createSemaphore("tics10thsec", COUNTING, 0); tics10sec = createSemaphore("tics10sec", COUNTING, 0); dcChange = createSemaphore("dcChange", BINARY, 0); //?? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // schedule CLI task createTask("myShell", // task name P1_shellTask, // task MED_PRIORITY , // task priority argc, // task arg count argv); // task argument pointers // HERE WE GO................ // Scheduling loop // 1. Check for asynchronous events (character inputs, timers, etc.) // 2. Choose a ready task to schedule // 3. Dispatch task // 4. Loop (forever!) while(1) // scheduling loop { // check for character / timer interrupts pollInterrupts(); // schedule highest priority ready task if ((curTask = scheduler()) < 0) continue; // dispatch curTask, quit OS if negative return if (dispatcher() < 0) break; } // end of scheduling loop // exit os longjmp(reset_context, POWER_DOWN_QUIT); return 0; } // end main