简体   繁体   English

如何在不使用C锁的情况下自动修改结构元素?

[英]How to modify structure elements atomically without using locks in C?

I would like to modify some elements of a structure atomically. 我想原子地修改结构的某些元素。 My current implementation uses mutexes to protect the critical code, and can be seen below. 我当前的实现使用互斥锁来保护关键代码,如下所示。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>

pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;

#define ITER    100000

typedef struct global_status {
    int32_t context_delta;
    uint32_t global_access_count;
} global_status_t;

global_status_t g_status;

void *context0(void *ptr)
{
    unsigned int iter = ITER;
    while (iter--) {
        wait_event_from_device0();
        pthread_mutex_lock(&thread_mutex);
        g_status.context_delta++;
        g_status.global_access_count++;
        pthread_mutex_unlock(&thread_mutex);
    }

    return NULL;
}

void *context1(void *ptr)
{
    unsigned int iter = ITER;
    while (iter--) {
        wait_event_from_device1();
        pthread_mutex_lock(&thread_mutex);
        g_status.context_delta--;
        g_status.global_access_count++;
        pthread_mutex_unlock(&thread_mutex);
    }

    return NULL;
}

int main(int argc, char **argv)
{
    pthread_t tid0, tid1;
    int iret;

    if ((iret = pthread_create(&tid0, NULL, context0, NULL))) {
         fprintf(stderr, "context0 creation error!\n");
         return EXIT_FAILURE;
    }

    if ((iret = pthread_create(&tid1, NULL, context1, NULL))) {
         fprintf(stderr, "context1 creation error!\n");
         return EXIT_FAILURE;
    }

    pthread_join(tid0, NULL);
    pthread_join(tid1, NULL);

    printf("%d, %d\n", g_status.context_delta, g_status.global_access_count);
    return 0;
}

I am planning to port this code into an RTOS which does not support posix, and I would like to do this operation atomically without using mutexes or disabling/enabling interrupts. 我打算将此代码移植到不支持posix的RTOS中,并且我希望自动执行此操作,而无需使用互斥锁或禁用/启用中断。

How can I do this operation? 我该怎么做? Is it possible by using 'atomic compare and swap function' (CAS)? 是否可以使用“原子比较和交换功能”(CAS)?

Seems like in your example you have two threads servicing to different devices. 好像在您的示例中,您有两个为不同设备提供服务的线程。 You maybe able to do away with locking completely using a per-device structure. 您也许可以使用每个设备的结构来完全锁定。 The global will be the aggregate of all per-device statistics. 全局将是所有每个设备统计信息的汇总。 If you do need locks you can use CAS, LL/SC or any supported underlying atomic construct. 如果确实需要锁,则可以使用CAS,LL / SC或任何受支持的基础原子构造。

What i do is create a union with all the fields I want to change at the same time. 我要做的是用我想同时更改的所有字段创建一个联合。 like this: 像这样:

union {
  struct {
    int            m_field1;
    unsigned short m_field2 : 2,
                   m_field3 : 1;
    BYTE           m_field4; 
  }
  unsigned long long m_n64;
  TData(const TData& r) { m_n64 = r.m_n64; }
} TData;

You embed unions like that inside your larger struct like this: 您可以像这样在更大的结构中嵌入工会:

struct {
  ...
  volatile TData m_Data;
  ...
} TBiggerStruct;

Then i do something like this: 然后我做这样的事情:

while (1) {
  TData Old = BiggerSharedStruct.m_Data, New = Old;
  New.field1++;
  New.field4--;
  if (CAS(&SharedData.m_n64, Old.m_n64, New.m_n64))
    break; // success
}

I do a lot of packing of fields that I want to change at the same time into the smallest possible 16, 32, or 64 bit structure. 我想将要同时更改为最小的16位,32位或64位结构的字段打包在一起。 I think 128 bit stuff on intel is not as fast as the 64 bit stuff, so I avoid it. 我认为intel上的128位填充不如64位填充快,因此我避免了。 I haven't benchmarked it in awhile so I could be wrong on that. 我有一段时间没有进行基准测试了,所以我可能会错了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM