<commit_before>// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/mach/mach_message_server.h"

#include <limits>

#include "base/mac/mach_logging.h"
#include "base/mac/scoped_mach_vm.h"
#include "util/misc/clock.h"

namespace crashpad {

namespace {

const int kNanosecondsPerMillisecond = 1E6;

// TimerRunning determines whether |deadline| has passed. If |deadline| is in
// the future, |*remaining_ms| is set to the number of milliseconds remaining,
// which will always be a positive value, and this function returns true. If
// |deadline| is zero (indicating that no timer is in effect), |*remaining_ms|
// is set to zero and this function returns true. Otherwise, this function
// returns false. |deadline| is specified on the same time base as is returned
// by ClockMonotonicNanoseconds().
bool TimerRunning(uint64_t deadline, mach_msg_timeout_t* remaining_ms) {
  if (!deadline) {
    *remaining_ms = MACH_MSG_TIMEOUT_NONE;
    return true;
  }

  uint64_t now = ClockMonotonicNanoseconds();

  if (now >= deadline) {
    return false;
  }

  uint64_t remaining = deadline - now;

  // Round to the nearest millisecond, taking care not to overflow.
  const int kHalfMillisecondInNanoseconds = kNanosecondsPerMillisecond / 2;
  mach_msg_timeout_t remaining_mach;
  if (remaining <=
      std::numeric_limits<uint64_t>::max() - kHalfMillisecondInNanoseconds) {
    remaining_mach = (remaining + kHalfMillisecondInNanoseconds) /
                     kNanosecondsPerMillisecond;
  } else {
    remaining_mach = remaining / kNanosecondsPerMillisecond;
  }

  if (remaining_mach == MACH_MSG_TIMEOUT_NONE) {
    return false;
  }

  *remaining_ms = remaining_mach;
  return true;
}

}  // namespace

// This implementation is based on 10.9.4
// xnu-2422.110.17/libsyscall/mach/mach_msg.c mach_msg_server_once(), but
// adapted to local style using scopers, replacing the server callback function
// and |max_size| parameter with a C++ interface, and with the addition of the
// the |persistent| parameter allowing this function to serve as a stand-in for
// mach_msg_server(), the |nonblocking| parameter to control blocking directly,
// and the |timeout_ms| parameter allowing this function to not block
// indefinitely.
//
// static
mach_msg_return_t MachMessageServer::Run(Interface* interface,
                                         mach_port_t receive_port,
                                         mach_msg_options_t options,
                                         Persistent persistent,
                                         Nonblocking nonblocking,
                                         ReceiveLarge receive_large,
                                         mach_msg_timeout_t timeout_ms) {
  options &= ~(MACH_RCV_MSG | MACH_SEND_MSG);

  mach_msg_options_t timeout_options = MACH_RCV_TIMEOUT | MACH_SEND_TIMEOUT |
                                       MACH_RCV_INTERRUPT | MACH_SEND_INTERRUPT;

  uint64_t deadline;
  if (nonblocking == kNonblocking) {
    options |= timeout_options;
    deadline = 0;
  } else if (timeout_ms != MACH_MSG_TIMEOUT_NONE) {
    options |= timeout_options;
    deadline = ClockMonotonicNanoseconds() +
               implicit_cast<uint64_t>(timeout_ms) * kNanosecondsPerMillisecond;
  } else {
    options &= ~timeout_options;
    deadline = 0;
  }

  if (receive_large == kReceiveLargeResize) {
    options |= MACH_RCV_LARGE;
  } else {
    options &= ~MACH_RCV_LARGE;
  }

  mach_msg_size_t trailer_alloc = REQUESTED_TRAILER_SIZE(options);
  mach_msg_size_t max_request_size = interface->MachMessageServerRequestSize();
  mach_msg_size_t request_alloc = round_page(max_request_size + trailer_alloc);
  mach_msg_size_t request_size = (receive_large == kReceiveLargeResize)
                                     ? request_alloc
                                     : max_request_size + trailer_alloc;

  mach_msg_size_t max_reply_size = interface->MachMessageServerReplySize();

  // mach_msg_server() and mach_msg_server_once() would consider whether<commit_msg>MachMessageServer: invert the request buffer allocation logic.<commit_after>// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/mach/mach_message_server.h"

#include <limits>

#include "base/mac/mach_logging.h"
#include "base/mac/scoped_mach_vm.h"
#include "util/misc/clock.h"

namespace crashpad {

namespace {

const int kNanosecondsPerMillisecond = 1E6;

// TimerRunning determines whether |deadline| has passed. If |deadline| is in
// the future, |*remaining_ms| is set to the number of milliseconds remaining,
// which will always be a positive value, and this function returns true. If
// |deadline| is zero (indicating that no timer is in effect), |*remaining_ms|
// is set to zero and this function returns true. Otherwise, this function
// returns false. |deadline| is specified on the same time base as is returned
// by ClockMonotonicNanoseconds().
bool TimerRunning(uint64_t deadline, mach_msg_timeout_t* remaining_ms) {
  if (!deadline) {
    *remaining_ms = MACH_MSG_TIMEOUT_NONE;
    return true;
  }

  uint64_t now = ClockMonotonicNanoseconds();

  if (now >= deadline) {
    return false;
  }

  uint64_t remaining = deadline - now;

  // Round to the nearest millisecond, taking care not to overflow.
  const int kHalfMillisecondInNanoseconds = kNanosecondsPerMillisecond / 2;
  mach_msg_timeout_t remaining_mach;
  if (remaining <=
      std::numeric_limits<uint64_t>::max() - kHalfMillisecondInNanoseconds) {
    remaining_mach = (remaining + kHalfMillisecondInNanoseconds) /
                     kNanosecondsPerMillisecond;
  } else {
    remaining_mach = remaining / kNanosecondsPerMillisecond;
  }

  if (remaining_mach == MACH_MSG_TIMEOUT_NONE) {
    return false;
  }

  *remaining_ms = remaining_mach;
  return true;
}

}  // namespace

// This implementation is based on 10.9.4
// xnu-2422.110.17/libsyscall/mach/mach_msg.c mach_msg_server_once(), but
// adapted to local style using scopers, replacing the server callback function
// and |max_size| parameter with a C++ interface, and with the addition of the
// the |persistent| parameter allowing this function to serve as a stand-in for
// mach_msg_server(), the |nonblocking| parameter to control blocking directly,
// and the |timeout_ms| parameter allowing this function to not block
// indefinitely.
//
// static
mach_msg_return_t MachMessageServer::Run(Interface* interface,
                                         mach_port_t receive_port,
                                         mach_msg_options_t options,
                                         Persistent persistent,
                                         Nonblocking nonblocking,
                                         ReceiveLarge receive_large,
                                         mach_msg_timeout_t timeout_ms) {
  options &= ~(MACH_RCV_MSG | MACH_SEND_MSG);

  mach_msg_options_t timeout_options = MACH_RCV_TIMEOUT | MACH_SEND_TIMEOUT |
                                       MACH_RCV_INTERRUPT | MACH_SEND_INTERRUPT;

  uint64_t deadline;
  if (nonblocking == kNonblocking) {
    options |= timeout_options;
    deadline = 0;
  } else if (timeout_ms != MACH_MSG_TIMEOUT_NONE) {
    options |= timeout_options;
    deadline = ClockMonotonicNanoseconds() +
               implicit_cast<uint64_t>(timeout_ms) * kNanosecondsPerMillisecond;
  } else {
    options &= ~timeout_options;
    deadline = 0;
  }

  if (receive_large == kReceiveLargeResize) {
    options |= MACH_RCV_LARGE;
  } else {
    options &= ~MACH_RCV_LARGE;
  }

  mach_msg_size_t trailer_alloc = REQUESTED_TRAILER_SIZE(options);
  mach_msg_size_t max_request_size = interface->MachMessageServerRequestSize();
  mach_msg_size_t request_alloc = round_page(max_request_size + trailer_alloc);

  // mach_msg_server() and mach_msg_server_once() invert this condition, but
  // their interpretation is incorrect. When it is desirable to retry a receive
  // attempt that returns MACH_RCV_TOO_LARGE with a larger receive buffer, it is
  // also desirable to use the full receive buffer rounded up to a page size for
  // the initial receive attempt. On the other hand, when this behavior is not
  // requested, there is no reason to attempt receiving messages any larger than
  // expected.
  mach_msg_size_t request_size = (receive_large == kReceiveLargeResize)
                                     ? max_request_size + trailer_alloc
                                     : request_alloc;

  mach_msg_size_t max_reply_size = interface->MachMessageServerReplySize();

  // mach_msg_server() and mach_msg_server_once() would consider whether
{'fraction_non_alphanumeric': 0.07855822550831792, 'fraction_numerical': 0.00780447730540152, 'mean_word_length': 3.0243801652892564, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1664863', 'n_tokens_mistral': 2924, 'n_tokens_neox': 2782, 'n_words': 846}