source: roaraudio/roard/memlock.c @ 5381:430b1d26e12d

Last change on this file since 5381:430b1d26e12d was 5381:430b1d26e12d, checked in by phi, 8 years ago

updated copyright years

File size: 4.8 KB
Line 
1//memlock.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#define MAX_SEGMENTS 16
29
30struct memlock {
31 int level;
32 void * addr;
33 size_t len;
34};
35
36static struct memlock memlock_table[MAX_SEGMENTS];
37
38static volatile int memlock_table_inited = 0;
39
40static void memlock_table_init (void) {
41 if ( memlock_table_inited )
42  return;
43
44 memset(memlock_table, 0, sizeof(memlock_table));
45
46 memlock_table_inited = 1;
47
48 memlock_register(MEMLOCK_MEDIUM, memlock_table, sizeof(memlock_table));
49
50 memlock_register(MEMLOCK_MEDIUM, g_clients, sizeof(g_clients));
51 memlock_register(MEMLOCK_MEDIUM, g_streams, sizeof(g_streams));
52
53 memlock_register(MEMLOCK_HIGH, g_listen, sizeof(g_listen));
54 memlock_register(MEMLOCK_HIGH, &g_counters, sizeof(g_counters));
55}
56
57int memlock_register(int level, void * addr, size_t len) {
58 int i;
59
60 if ( !memlock_table_inited )
61  memlock_table_init();
62
63 for (i = 0; i < MAX_SEGMENTS; i++) {
64  if ( memlock_table[i].addr == NULL ) {
65   memlock_table[i].level = level;
66   memlock_table[i].addr  = addr;
67   memlock_table[i].len   = len;
68   return 0;
69  }
70 }
71
72 return -1;
73}
74
75static inline int memlock_lock(struct memlock * seg) {
76 return roar_mm_mlock(seg->addr, seg->len);
77}
78
79static inline int memlock_unlock(struct memlock * seg) {
80 return roar_mm_munlock(seg->addr, seg->len);
81}
82
83int memlock_str2level(const char * str) {
84 if ( str == NULL )
85  return -1;
86
87 if ( !strcasecmp(str, "none") ) {
88  return MEMLOCK_NONE;
89 } else if ( !strcasecmp(str, "low") ) {
90  return MEMLOCK_LOW;
91 } else if ( !strcasecmp(str, "medium") ) {
92  return MEMLOCK_MEDIUM;
93 } else if ( !strcasecmp(str, "high") ) {
94  return MEMLOCK_HIGH;
95 } else if ( !strcasecmp(str, "nearlyall") ) {
96  return MEMLOCK_NEARLYALL;
97 } else if ( !strcasecmp(str, "nearlyallsys") ) {
98  return MEMLOCK_NEARLYALLSYS;
99 } else if ( !strcasecmp(str, "allcur") ) {
100  return MEMLOCK_ALLCUR;
101 } else if ( !strcasecmp(str, "all") ) {
102  return MEMLOCK_ALL;
103 } else if ( !strcasecmp(str, "default") ) {
104  return MEMLOCK_DEFAULT;
105 } else {
106  return -1;
107 }
108}
109
110int memlock_set_level(int level) {
111 static int old_level = MEMLOCK_NONE;
112 int i;
113 int ret = 0;
114
115 ROAR_DBG("memlock_set_level(level=%i) = ?", level);
116
117 ROAR_DBG("memlock_set_level(level=%i): ask for locking level change: %i->%i", level, old_level, level);
118
119 if ( !memlock_table_inited )
120  memlock_table_init();
121
122 if ( level == old_level ) {
123  ROAR_DBG("memlock_set_level(level=%i) = 0 // old and new level are the same, nothing to do", level);
124  return 0;
125 }
126
127 // TODO: fix those #ifdefs and replace them with more general tests
128 if ( level == MEMLOCK_ALL ) {
129#ifdef ROAR_HAVE_MLOCKALL
130  // if we do not have ROAR_HAVE_MLOCKALL we do not have MCL_* flags.
131  // we just try to lock all known segments as fallback.
132  old_level = MEMLOCK_ALL;
133  return roar_mm_mlockall(MCL_CURRENT|MCL_FUTURE);
134#endif
135 } else if ( level == MEMLOCK_ALLCUR ) {
136#ifdef ROAR_HAVE_MLOCKALL
137  old_level = MEMLOCK_ALLCUR;
138  return roar_mm_mlockall(MCL_CURRENT);
139#endif
140 } else if ( old_level == MEMLOCK_ALL || old_level == MEMLOCK_ALLCUR ) {
141#ifdef ROAR_HAVE_MUNLOCKALL
142  ret = roar_mm_munlockall();
143  // after roar_mm_munlockall() we need to re-lock all segemnts of target locking level.
144  i = old_level;
145  old_level = MEMLOCK_NONE;
146  return memlock_set_level(i);
147#endif
148 }
149
150 for (i = 0; i < MAX_SEGMENTS; i++) {
151  if ( memlock_table[i].addr != NULL ) {
152   ROAR_DBG("memlock_set_level(level=%i): found registerd segment %i at %p with %llu Byte length", level, i, memlock_table[i].addr, (unsigned long long int)memlock_table[i].len);
153   if ( level > old_level ) {
154    if ( memlock_table[i].level > old_level && memlock_table[i].level <= level )
155     if ( memlock_lock(&(memlock_table[i])) == -1 )
156      ret = -1;
157   } else {
158    if ( memlock_table[i].level <= old_level && memlock_table[i].level > level )
159     if ( memlock_unlock(&(memlock_table[i])) == -1 )
160      ret = -1;
161   }
162  }
163 }
164
165 old_level = level;
166
167 ROAR_DBG("memlock_set_level(level=%i) = %i", level, ret);
168 return ret;
169}
170
171void memlock_unload() {
172}
173
174void memlock_reload() {
175}
176
177//ll
Note: See TracBrowser for help on using the repository browser.