aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/common/io_service_args.cpp
blob: 8be1ff89b74447e244491d09caacb2d98c9b0509 (plain)
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
//
// Copyright 2019 Ettus Research, a National Instruments brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#include <uhd/utils/log.hpp>
#include <uhdlib/usrp/common/io_service_args.hpp>
#include <uhdlib/usrp/constrained_device_args.hpp>
#include <boost/format.hpp>
#include <regex>
#include <string>

static const std::string LOG_ID = "IO_SRV";

static const char* recv_offload_str             = "recv_offload";
static const char* send_offload_str             = "send_offload";
static const char* recv_offload_wait_mode_str   = "recv_offload_wait_mode";
static const char* send_offload_wait_mode_str   = "send_offload_wait_mode";
static const char* num_poll_offload_threads_str = "num_poll_offload_threads";

static const std::regex recv_offload_thread_cpu_expr("^recv_offload_thread_(\\d+)_cpu");
static const std::regex send_offload_thread_cpu_expr("^send_offload_thread_(\\d+)_cpu");
static const std::regex poll_offload_thread_cpu_expr("^poll_offload_thread_(\\d+)_cpu");

namespace uhd { namespace usrp {

namespace {

bool get_bool_arg(const device_addr_t& args, const std::string& key, const bool def)
{
    constrained_device_args_t::bool_arg arg(key, def);
    if (args.has_key(key)) {
        arg.parse(args[key]);
    }
    return arg.get();
}

io_service_args_t::wait_mode_t get_wait_mode_arg(const device_addr_t& args,
    const std::string& key,
    const io_service_args_t::wait_mode_t def)
{
    constrained_device_args_t::enum_arg<io_service_args_t::wait_mode_t> arg(key,
        def,
        {{"poll", io_service_args_t::POLL}, {"block", io_service_args_t::BLOCK}});

    if (args.has_key(key)) {
        arg.parse(args[key]);
    }
    return arg.get();
}

}; // namespace

io_service_args_t read_io_service_args(
    const device_addr_t& args, const io_service_args_t& defaults)
{
    io_service_args_t io_srv_args;
    std::string tmp_str, default_str;

    io_srv_args.recv_offload =
        get_bool_arg(args, recv_offload_str, defaults.recv_offload);
    io_srv_args.send_offload =
        get_bool_arg(args, send_offload_str, defaults.send_offload);

    io_srv_args.recv_offload_wait_mode = get_wait_mode_arg(
        args, recv_offload_wait_mode_str, defaults.recv_offload_wait_mode);
    io_srv_args.send_offload_wait_mode = get_wait_mode_arg(
        args, send_offload_wait_mode_str, defaults.send_offload_wait_mode);

    io_srv_args.num_poll_offload_threads = args.cast<size_t>(
        num_poll_offload_threads_str, defaults.num_poll_offload_threads);
    if (io_srv_args.num_poll_offload_threads == 0) {
        UHD_LOG_WARNING(LOG_ID,
            "Invalid value for num_poll_offload_threads. "
            "Value must be greater than 0.");
        io_srv_args.num_poll_offload_threads = 1;
    }

    auto read_thread_args = [&args](
                                const std::regex& expr, std::map<size_t, size_t>& dest) {
        auto keys = args.keys();
        for (const auto& key : keys) {
            std::smatch match;
            if (std::regex_match(key, match, expr)) {
                UHD_ASSERT_THROW(match.size() == 2); // first match is the entire key
                const size_t thread = std::stoul(match.str(1));
                const size_t cpu    = args.cast<size_t>(key, 0);
                dest[thread]        = cpu;
            }
        }
    };

    read_thread_args(recv_offload_thread_cpu_expr, io_srv_args.recv_offload_thread_cpu);
    read_thread_args(send_offload_thread_cpu_expr, io_srv_args.send_offload_thread_cpu);
    read_thread_args(poll_offload_thread_cpu_expr, io_srv_args.poll_offload_thread_cpu);

    return io_srv_args;
}

device_addr_t merge_io_service_dev_args(
    const device_addr_t& dev_args, const device_addr_t& stream_args)
{
    device_addr_t args = stream_args;

    auto merge_args = [](const device_addr_t& dev_args,
                          device_addr_t& stream_args,
                          const std::string& key) {
        if (!stream_args.has_key(key)) {
            if (dev_args.has_key(key)) {
                stream_args[key] = dev_args[key];
            }
        }
    };

    merge_args(dev_args, args, recv_offload_str);
    merge_args(dev_args, args, send_offload_str);
    merge_args(dev_args, args, recv_offload_wait_mode_str);
    merge_args(dev_args, args, send_offload_wait_mode_str);
    merge_args(dev_args, args, num_poll_offload_threads_str);

    auto merge_thread_args = [&merge_args](const device_addr_t& dev_args,
                                 device_addr_t& stream_args,
                                 const std::regex& expr) {
        auto keys = dev_args.keys();
        for (const auto& key : keys) {
            std::smatch match;
            if (std::regex_match(key, match, expr)) {
                merge_args(dev_args, stream_args, key);
            }
        }
    };

    merge_thread_args(dev_args, args, recv_offload_thread_cpu_expr);
    merge_thread_args(dev_args, args, send_offload_thread_cpu_expr);
    merge_thread_args(dev_args, args, poll_offload_thread_cpu_expr);

    return args;
}

}} // namespace uhd::usrp