status_t MessagingService::SendMessage(const void *message, int32 messageSize, const messaging_target *targets, int32 targetCount) { PRINT(("MessagingService::SendMessage(%p, %ld, %p, %ld)\n", message, messageSize, targets, targetCount)); if (!message || messageSize <= 0 || !targets || targetCount <= 0) return B_BAD_VALUE; int32 dataSize = sizeof(messaging_command_send_message) + targetCount * sizeof(messaging_target) + messageSize; // allocate space for the command MessagingArea *area; void *data; bool wasEmpty; status_t error = _AllocateCommand(MESSAGING_COMMAND_SEND_MESSAGE, dataSize, area, data, wasEmpty); if (error != B_OK) { PRINT(("MessagingService::SendMessage(): Failed to allocate space for " "send message command.\n")); return error; } PRINT((" Allocated space for send message command: area: %p, data: %p, " "wasEmpty: %d\n", area, data, wasEmpty)); // prepare the command messaging_command_send_message *command = (messaging_command_send_message*)data; command->message_size = messageSize; command->target_count = targetCount; memcpy(command->targets, targets, sizeof(messaging_target) * targetCount); memcpy((char*)command + (dataSize - messageSize), message, messageSize); // shoot area->Unlock(); if (wasEmpty) area->CommitCommand(); return B_OK; }
// _CommandProcessor int32 MessagingService::_CommandProcessor() { bool commandWaiting = false; while (!fTerminating) { // wait for the next command if (!commandWaiting) { status_t error = acquire_sem(fCounterSem); if (error != B_OK) continue; } else commandWaiting = false; // get it from the first area MessagingArea *area = fFirstArea; area->Lock(); while (area->CountCommands() > 0) { const messaging_command *command = area->PopCommand(); if (!command) { // something's seriously wrong ERROR("MessagingService::_CommandProcessor(): area %p (%" B_PRId32 ") has command count %" B_PRId32 ", but doesn't " "return any more commands.", area, area->ID(), area->CountCommands()); break; } PRINT("MessagingService::_CommandProcessor(): got command %" B_PRIu32 "\n", command->command); // dispatch the command MessagingCommandHandler *handler = _GetCommandHandler(command->command); if (handler) { handler->HandleMessagingCommand(command->command, command->data, command->size - sizeof(messaging_command)); } else { WARNING("MessagingService::_CommandProcessor(): No handler " "found for command %" B_PRIu32 "\n", command->command); } } // there is a new area we don't know yet if (!area->NextArea() && area->NextKernelAreaID() >= 0) { // create it MessagingArea *nextArea; status_t error = MessagingArea::Create(area->NextKernelAreaID(), fLockSem, fCounterSem, nextArea); if (error == B_OK) { area->SetNextArea(nextArea); commandWaiting = true; } else { // Bad, but what can we do? ERROR("MessagingService::_CommandProcessor(): Failed to clone " "kernel area %" B_PRId32 ": %s\n", area->NextKernelAreaID(), strerror(error)); } } // if the current area is empty and there is a next one, we discard the // current one if (area->NextArea() && area->CountCommands() == 0) { fFirstArea = area->NextArea(); area->Discard(); area->Unlock(); delete area; } else { area->Unlock(); } } return 0; }