Skip to content

Commit 0a87c2d

Browse files
Ola Tangen Kulsengcarlescufi
authored andcommitted
net: lwm2m: Thread safe lwm2m registry
Created the mutex registry_lock to: - protect read and write operations - protect the registry. Only partially finished as the functions like lwm2m_engine_get_obj warrants a larger refactoring to completely thread safe the registry. Signed-off-by: Ola Tangen Kulseng <[email protected]>
1 parent 534c7f2 commit 0a87c2d

File tree

1 file changed

+48
-8
lines changed

1 file changed

+48
-8
lines changed

subsys/net/lib/lwm2m/lwm2m_registry.c

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
4040
#define BINDING_OPT_MAX_LEN 3 /* "UQ" */
4141
#define QUEUE_OPT_MAX_LEN 2 /* "Q" */
4242

43+
static K_MUTEX_DEFINE(registry_lock);
4344
/* Resources */
4445
static sys_slist_t engine_obj_list;
4546
static sys_slist_t engine_obj_inst_list;
@@ -53,6 +54,7 @@ sys_slist_t *lwm2m_engine_obj_inst_list(void) { return &engine_obj_inst_list; }
5354

5455
void lwm2m_register_obj(struct lwm2m_engine_obj *obj)
5556
{
57+
k_mutex_lock(&registry_lock, K_FOREVER);
5658
#if defined(CONFIG_LWM2M_ACCESS_CONTROL_ENABLE)
5759
/* If bootstrap, then bootstrap server should create the ac obj instances */
5860
#if !IS_ENABLED(CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP)
@@ -62,15 +64,18 @@ void lwm2m_register_obj(struct lwm2m_engine_obj *obj)
6264
#endif /* CONFIG_LWM2M_RD_CLIENT_SUPPORT_BOOTSTRAP */
6365
#endif /* CONFIG_LWM2M_ACCESS_CONTROL_ENABLE */
6466
sys_slist_append(&engine_obj_list, &obj->node);
67+
k_mutex_unlock(&registry_lock);
6568
}
6669

6770
void lwm2m_unregister_obj(struct lwm2m_engine_obj *obj)
6871
{
72+
k_mutex_lock(&registry_lock, K_FOREVER);
6973
#if defined(CONFIG_LWM2M_ACCESS_CONTROL_ENABLE)
7074
access_control_remove_obj(obj->obj_id);
7175
#endif
7276
engine_remove_observer_by_id(obj->obj_id, -1);
7377
sys_slist_find_and_remove(&engine_obj_list, &obj->node);
78+
k_mutex_unlock(&registry_lock);
7479
}
7580

7681
struct lwm2m_engine_obj *get_engine_obj(int obj_id)
@@ -163,23 +168,27 @@ struct lwm2m_engine_obj_inst *next_engine_obj_inst(int obj_id, int obj_inst_id)
163168
int lwm2m_create_obj_inst(uint16_t obj_id, uint16_t obj_inst_id,
164169
struct lwm2m_engine_obj_inst **obj_inst)
165170
{
171+
k_mutex_lock(&registry_lock, K_FOREVER);
166172
struct lwm2m_engine_obj *obj;
167173
int ret;
168174

169175
*obj_inst = NULL;
170176
obj = get_engine_obj(obj_id);
171177
if (!obj) {
172178
LOG_ERR("unable to find obj: %u", obj_id);
179+
k_mutex_unlock(&registry_lock);
173180
return -ENOENT;
174181
}
175182

176183
if (!obj->create_cb) {
177184
LOG_ERR("obj %u has no create_cb", obj_id);
185+
k_mutex_unlock(&registry_lock);
178186
return -EINVAL;
179187
}
180188

181189
if (obj->instance_count + 1 > obj->max_instance_count) {
182190
LOG_ERR("no more instances available for obj %u", obj_id);
191+
k_mutex_unlock(&registry_lock);
183192
return -ENOMEM;
184193
}
185194

@@ -190,6 +199,7 @@ int lwm2m_create_obj_inst(uint16_t obj_id, uint16_t obj_inst_id,
190199
* Already checked for instance count total.
191200
* This can only be an error if the object instance exists.
192201
*/
202+
k_mutex_unlock(&registry_lock);
193203
return -EEXIST;
194204
}
195205

@@ -202,27 +212,31 @@ int lwm2m_create_obj_inst(uint16_t obj_id, uint16_t obj_inst_id,
202212
ret = obj->user_create_cb(obj_inst_id);
203213
if (ret < 0) {
204214
LOG_ERR("Error in user obj create %u/%u: %d", obj_id, obj_inst_id, ret);
215+
k_mutex_unlock(&registry_lock);
205216
lwm2m_delete_obj_inst(obj_id, obj_inst_id);
206217
return ret;
207218
}
208219
}
209-
220+
k_mutex_unlock(&registry_lock);
210221
return 0;
211222
}
212223

213224
int lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id)
214225
{
226+
k_mutex_lock(&registry_lock, K_FOREVER);
215227
int i, ret = 0;
216228
struct lwm2m_engine_obj *obj;
217229
struct lwm2m_engine_obj_inst *obj_inst;
218230

219231
obj = get_engine_obj(obj_id);
220232
if (!obj) {
233+
k_mutex_unlock(&registry_lock);
221234
return -ENOENT;
222235
}
223236

224237
obj_inst = get_engine_obj_inst(obj_id, obj_inst_id);
225238
if (!obj_inst) {
239+
k_mutex_unlock(&registry_lock);
226240
return -ENOENT;
227241
}
228242

@@ -249,6 +263,7 @@ int lwm2m_delete_obj_inst(uint16_t obj_id, uint16_t obj_inst_id)
249263

250264
clear_attrs(obj_inst);
251265
(void)memset(obj_inst, 0, sizeof(struct lwm2m_engine_obj_inst));
266+
k_mutex_unlock(&registry_lock);
252267
return ret;
253268
}
254269

@@ -417,14 +432,17 @@ int lwm2m_engine_set_res_buf(const char *pathstr, void *buffer_ptr, uint16_t buf
417432
return -EINVAL;
418433
}
419434

435+
k_mutex_lock(&registry_lock, K_FOREVER);
420436
/* look up resource obj */
421437
ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst);
422438
if (ret < 0) {
439+
k_mutex_unlock(&registry_lock);
423440
return ret;
424441
}
425442

426443
if (!res_inst) {
427444
LOG_ERR("res instance %d not found", path.res_inst_id);
445+
k_mutex_unlock(&registry_lock);
428446
return -ENOENT;
429447
}
430448

@@ -434,6 +452,7 @@ int lwm2m_engine_set_res_buf(const char *pathstr, void *buffer_ptr, uint16_t buf
434452
res_inst->max_data_len = buffer_len;
435453
res_inst->data_flags = data_flags;
436454

455+
k_mutex_unlock(&registry_lock);
437456
return ret;
438457
}
439458

@@ -468,21 +487,25 @@ static int lwm2m_engine_set(const char *pathstr, void *value, uint16_t len)
468487
return -EINVAL;
469488
}
470489

490+
k_mutex_lock(&registry_lock, K_FOREVER);
471491
/* look up resource obj */
472492
ret = path_to_objs(&path, &obj_inst, &obj_field, &res, &res_inst);
473493
if (ret < 0) {
494+
k_mutex_unlock(&registry_lock);
474495
return ret;
475496
}
476497

477498
if (!res_inst) {
478499
LOG_ERR("res instance %d not found", path.res_inst_id);
500+
k_mutex_unlock(&registry_lock);
479501
return -ENOENT;
480502
}
481503

482504
if (LWM2M_HAS_RES_FLAG(res_inst, LWM2M_RES_DATA_FLAG_RO)) {
483505
LOG_ERR("res instance data pointer is read-only "
484506
"[%u/%u/%u/%u:%u]",
485507
path.obj_id, path.obj_inst_id, path.res_id, path.res_inst_id, path.level);
508+
k_mutex_unlock(&registry_lock);
486509
return -EACCES;
487510
}
488511

@@ -499,12 +522,14 @@ static int lwm2m_engine_set(const char *pathstr, void *value, uint16_t len)
499522
if (!data_ptr) {
500523
LOG_ERR("res instance data pointer is NULL [%u/%u/%u/%u:%u]", path.obj_id,
501524
path.obj_inst_id, path.res_id, path.res_inst_id, path.level);
525+
k_mutex_unlock(&registry_lock);
502526
return -EINVAL;
503527
}
504528

505529
/* check length (note: we add 1 to string length for NULL pad) */
506530
if (len > max_data_len - (obj_field->data_type == LWM2M_RES_TYPE_STRING ? 1 : 0)) {
507531
LOG_ERR("length %u is too long for res instance %d data", len, path.res_id);
532+
k_mutex_unlock(&registry_lock);
508533
return -ENOMEM;
509534
}
510535

@@ -517,6 +542,7 @@ static int lwm2m_engine_set(const char *pathstr, void *value, uint16_t len)
517542
ret = res->validate_cb(obj_inst->obj_inst_id, res->res_id, res_inst->res_inst_id,
518543
value, len, false, 0);
519544
if (ret < 0) {
545+
k_mutex_unlock(&registry_lock);
520546
return -EINVAL;
521547
}
522548
}
@@ -576,6 +602,7 @@ static int lwm2m_engine_set(const char *pathstr, void *value, uint16_t len)
576602

577603
default:
578604
LOG_ERR("unknown obj data_type %d", obj_field->data_type);
605+
k_mutex_unlock(&registry_lock);
579606
return -EINVAL;
580607
}
581608

@@ -589,7 +616,7 @@ static int lwm2m_engine_set(const char *pathstr, void *value, uint16_t len)
589616
if (changed && LWM2M_HAS_PERM(obj_field, LWM2M_PERM_R)) {
590617
lwm2m_notify_observer_path(&path);
591618
}
592-
619+
k_mutex_unlock(&registry_lock);
593620
return ret;
594621
}
595622

@@ -694,14 +721,17 @@ int lwm2m_engine_get_res_buf(const char *pathstr, void **buffer_ptr, uint16_t *b
694721
return -EINVAL;
695722
}
696723

724+
k_mutex_lock(&registry_lock, K_FOREVER);
697725
/* look up resource obj */
698726
ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst);
699727
if (ret < 0) {
728+
k_mutex_unlock(&registry_lock);
700729
return ret;
701730
}
702731

703732
if (!res_inst) {
704733
LOG_ERR("res instance %d not found", path.res_inst_id);
734+
k_mutex_unlock(&registry_lock);
705735
return -ENOENT;
706736
}
707737

@@ -718,6 +748,7 @@ int lwm2m_engine_get_res_buf(const char *pathstr, void **buffer_ptr, uint16_t *b
718748
*data_flags = res_inst->data_flags;
719749
}
720750

751+
k_mutex_unlock(&registry_lock);
721752
return 0;
722753
}
723754

@@ -750,15 +781,17 @@ static int lwm2m_engine_get(const char *pathstr, void *buf, uint16_t buflen)
750781
LOG_ERR("path must have at least 3 parts");
751782
return -EINVAL;
752783
}
753-
784+
k_mutex_lock(&registry_lock, K_FOREVER);
754785
/* look up resource obj */
755786
ret = path_to_objs(&path, &obj_inst, &obj_field, &res, &res_inst);
756787
if (ret < 0) {
788+
k_mutex_unlock(&registry_lock);
757789
return ret;
758790
}
759791

760792
if (!res_inst) {
761793
LOG_ERR("res instance %d not found", path.res_inst_id);
794+
k_mutex_unlock(&registry_lock);
762795
return -ENOENT;
763796
}
764797

@@ -779,6 +812,7 @@ static int lwm2m_engine_get(const char *pathstr, void *buf, uint16_t buflen)
779812

780813
case LWM2M_RES_TYPE_OPAQUE:
781814
if (data_len > buflen) {
815+
k_mutex_unlock(&registry_lock);
782816
return -ENOMEM;
783817
}
784818

@@ -832,10 +866,11 @@ static int lwm2m_engine_get(const char *pathstr, void *buf, uint16_t buflen)
832866

833867
default:
834868
LOG_ERR("unknown obj data_type %d", obj_field->data_type);
869+
k_mutex_unlock(&registry_lock);
835870
return -EINVAL;
836871
}
837872
}
838-
873+
k_mutex_unlock(&registry_lock);
839874
return 0;
840875
}
841876

@@ -1056,22 +1091,25 @@ int lwm2m_engine_create_res_inst(const char *pathstr)
10561091
LOG_ERR("path must have 4 parts");
10571092
return -EINVAL;
10581093
}
1059-
1094+
k_mutex_lock(&registry_lock, K_FOREVER);
10601095
ret = path_to_objs(&path, NULL, NULL, &res, &res_inst);
10611096
if (ret < 0) {
1097+
k_mutex_unlock(&registry_lock);
10621098
return ret;
10631099
}
10641100

10651101
if (!res) {
10661102
LOG_ERR("resource %u not found", path.res_id);
1103+
k_mutex_unlock(&registry_lock);
10671104
return -ENOENT;
10681105
}
10691106

10701107
if (res_inst && res_inst->res_inst_id != RES_INSTANCE_NOT_CREATED) {
10711108
LOG_ERR("res instance %u already exists", path.res_inst_id);
1109+
k_mutex_unlock(&registry_lock);
10721110
return -EINVAL;
10731111
}
1074-
1112+
k_mutex_unlock(&registry_lock);
10751113
return lwm2m_engine_allocate_resource_instance(res, &res_inst, path.res_inst_id);
10761114
}
10771115

@@ -1090,22 +1128,24 @@ int lwm2m_engine_delete_res_inst(const char *pathstr)
10901128
LOG_ERR("path must have 4 parts");
10911129
return -EINVAL;
10921130
}
1093-
1131+
k_mutex_lock(&registry_lock, K_FOREVER);
10941132
ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst);
10951133
if (ret < 0) {
1134+
k_mutex_unlock(&registry_lock);
10961135
return ret;
10971136
}
10981137

10991138
if (!res_inst) {
11001139
LOG_ERR("res instance %u not found", path.res_inst_id);
1140+
k_mutex_unlock(&registry_lock);
11011141
return -ENOENT;
11021142
}
11031143

11041144
res_inst->data_ptr = NULL;
11051145
res_inst->max_data_len = 0U;
11061146
res_inst->data_len = 0U;
11071147
res_inst->res_inst_id = RES_INSTANCE_NOT_CREATED;
1108-
1148+
k_mutex_unlock(&registry_lock);
11091149
return 0;
11101150
}
11111151
/* Register callbacks */

0 commit comments

Comments
 (0)