raindrops.git  about / heads / tags
real-time stats for preforking Rack servers
blob 86c7d7830669d36be83a596928839ba54739c5cf 4321 bytes (raw)
$ git show freebsd:ext/raindrops/extconf.rb	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
 
require 'mkmf'
require 'shellwords'

dir_config('atomic_ops')
have_func('mmap', 'sys/mman.h') or abort 'mmap() not found'
have_func('munmap', 'sys/mman.h') or abort 'munmap() not found'

$CPPFLAGS += " -D_GNU_SOURCE "
have_func('mremap', 'sys/mman.h')
headers = %w(sys/types.h netdb.h string.h sys/socket.h netinet/in.h)
if have_header('linux/tcp.h')
  headers << 'linux/tcp.h'
else
  %w(netinet/tcp.h netinet/tcp_fsm.h).each { |h|
    have_header(h, headers) and headers << h
  }
end

$CPPFLAGS += " -D_BSD_SOURCE "

if have_type("struct tcp_info", headers)
  %w(
    tcpi_state
    tcpi_ca_state
    tcpi_retransmits
    tcpi_probes
    tcpi_backoff
    tcpi_options
    tcpi_snd_wscale
    tcpi_rcv_wscale
    tcpi_rto
    tcpi_ato
    tcpi_snd_mss
    tcpi_rcv_mss
    tcpi_unacked
    tcpi_sacked
    tcpi_lost
    tcpi_retrans
    tcpi_fackets
    tcpi_last_data_sent
    tcpi_last_ack_sent
    tcpi_last_data_recv
    tcpi_last_ack_recv
    tcpi_pmtu
    tcpi_rcv_ssthresh
    tcpi_rtt
    tcpi_rttvar
    tcpi_snd_ssthresh
    tcpi_snd_cwnd
    tcpi_advmss
    tcpi_reordering
    tcpi_rcv_rtt
    tcpi_rcv_space
    tcpi_total_retrans
    tcpi_snd_wnd
    tcpi_snd_bwnd
    tcpi_snd_nxt
    tcpi_rcv_nxt
    tcpi_toe_tid
    tcpi_snd_rexmitpack
    tcpi_rcv_ooopack
    tcpi_snd_zerowin
  ).each do |field|
    cfunc = "tcp_info_#{field}"
    if have_struct_member('struct tcp_info', field, headers)
      func_body = <<EOF
static VALUE #{cfunc}(VALUE self)
{
	struct tcp_info *info = DATA_PTR(self);
	return UINT2NUM((uint32_t)info->#{field});
}
EOF
      func_body.delete!("\n")
      $defs << "-DCFUNC_#{cfunc}=#{Shellwords.shellescape(func_body)}"
    else
      func_body = "static inline void #{cfunc}(void) {}"
      $defs << "-DCFUNC_#{cfunc}=#{Shellwords.shellescape(func_body)}"
      cfunc = 'rb_f_notimplement'.freeze
    end
    rbmethod = %Q("#{field.sub(/\Atcpi_/, ''.freeze)}")
    $defs << "-DDEFINE_METHOD_tcp_info_#{field}=" \
	     "#{Shellwords.shellescape(
                %Q[rb_define_method(cTCP_Info,#{rbmethod},#{cfunc},0)])}"
  end
  tcp_state_map = {
    ESTABLISHED: %w(TCP_ESTABLISHED TCPS_ESTABLISHED),
    SYN_SENT: %w(TCP_SYN_SENT TCPS_SYN_SENT),
    SYN_RECV: %w(TCP_SYN_RECV TCPS_SYN_RECEIVED),
    FIN_WAIT1: %w(TCP_FIN_WAIT1 TCPS_FIN_WAIT_1),
    FIN_WAIT2: %w(TCP_FIN_WAIT2 TCPS_FIN_WAIT_2),
    TIME_WAIT: %w(TCP_TIME_WAIT TCPS_TIME_WAIT),
    CLOSE: %w(TCP_CLOSE TCPS_CLOSED),
    CLOSE_WAIT: %w(TCP_CLOSE_WAIT TCPS_CLOSE_WAIT),
    LAST_ACK: %w(TCP_LAST_ACK TCPS_LAST_ACK),
    LISTEN: %w(TCP_LISTEN TCPS_LISTEN),
    CLOSING: %w(TCP_CLOSING TCPS_CLOSING),
  }
  nstate = 0
  tcp_state_map.each do |state, try|
    try.each do |os_name|
      have_const(os_name, headers) or next
      tcp_state_map[state] = os_name
      nstate += 1
    end
  end
  if nstate == tcp_state_map.size
    $defs << '-DRAINDROPS_TCP_STATES_ALL_KNOWN=1'
    tcp_state_map.each do |state, name|
      $defs << "-DRAINDROPS_TCP_#{state}=#{name}"
    end
  end
end

have_func("getpagesize", "unistd.h")
have_func('rb_thread_blocking_region')
have_func('rb_thread_io_blocking_region')

checking_for "GCC 4+ atomic builtins" do
  # we test CMPXCHG anyways even though we don't need it to filter out
  # ancient i386-only targets without CMPXCHG
  src = <<SRC
int main(int argc, char * const argv[]) {
        unsigned long i = 0;
        __sync_lock_test_and_set(&i, 0);
        __sync_lock_test_and_set(&i, 1);
        __sync_bool_compare_and_swap(&i, 0, 1);
        __sync_add_and_fetch(&i, argc);
        __sync_sub_and_fetch(&i, argc);
        return 0;
}
SRC

  if try_link(src)
    $defs.push(format("-DHAVE_GCC_ATOMIC_BUILTINS"))
    true
  else
    # some compilers still target 386 by default, but we need at least 486
    # to run atomic builtins.
    prev_cflags = $CFLAGS
    $CFLAGS += " -march=i486 "
    if try_link(src)
      $defs.push(format("-DHAVE_GCC_ATOMIC_BUILTINS"))
      true
    else
      prev_cflags = $CFLAGS
      false
    end
  end
end or have_header('atomic_ops.h') or abort <<-SRC

libatomic_ops is required if GCC 4+ is not used.
See https://github.com/ivmai/libatomic_ops

Users of Debian-based distros may run:

  apt-get install libatomic-ops-dev
SRC
create_header # generate extconf.h to avoid excessively long command-line
create_makefile('raindrops_ext')

git clone https://yhbt.net/raindrops.git