I am starting to learn to write PCI driver and the first exercise i took was to find if a given device exists on the bus. After searching some books and internet, i was able to write down the below program which does work but i am not clear on few concepts.
1 /*
2 Program to find a device on the PCI sub-system
3 */
4 #define VENDOR_ID 0x8086
5 #define DEVICE_ID 0x7113
6
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/stddef.h>
10 #include <linux/pci.h>
11 #include <linux/init.h>
12 #include <linux/cdev.h>
13 #include <linux/device.h>
14
15 #define LOG(string...) printk(KERN_NOTICE string)
16
17 #define CDEV_MAJOR 227
18 #define CDEV_MINOR 0
19
20
21 MODULE_LICENSE("GPL");
22
23 struct pci_dev *pci_dev;
24 unsigned long mmio_addr;
25 unsigned long reg_len;
26 unsigned long *base_addr;
27
28 int device_probe(struct pci_dev *dev, const struct pci_device_id *id);
29 void device_remove(struct pci_dev *dev);
30
31 struct pci_device_id pci_device_id_DevicePCI[] =
32 {
33 {VENDOR_ID, DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
34 {} // end of list
35 };
36
37 struct pci_driver pci_driver_DevicePCI =
38 {
39 name: "MyPCIDevice",
40 id_table: pci_device_id_DevicePCI,
41 probe: device_probe,
42 remove: device_remove
43 };
44
45
46 int init_module(void)
47 {
48 struct pci_dev *pdev = NULL;
49 int ret = 0;
50
51 pci_register_driver(&pci_driver_DevicePCI);
52 pdev = pci_get_device(VENDOR_ID, DEVICE_ID, NULL);
53 if (pdev)
54 {
55 LOG("Device found ... ");
56 pci_dev = pdev;
57 }
58 else
59 {
60 LOG("Device not found ... ");
61 }
62 return ret;
63
64
65 }
66
67 void cleanup_module(void)
68 {
69 pci_unregister_driver(&pci_driver_DevicePCI);
70
71 }
72
73 int device_probe(struct pci_dev *dev, const struct pci_device_id *id)
74 {
75 int ret;
76 LOG("Devie probed");
77 ret = pci_enable_device(dev);
78 if (ret < 0 ) LOG("Failed while enabling ... ");
79
80 return ret;
81 }
82
83 void device_remove(struct pci_dev *dev)
84 {
85 pci_release_regions(dev);
86 pci_disable_device(dev);
87 }
Inside init_module() function, given user VID and DID device is found and if successful, struct pdev is pointing to the respective pci device. As i have read, probe() function kicks in as soon as the device is found.
Does this mean we always have to do pci_get_device() before calling the pci_enable_device()?
IMO, yes but if so, how do device_probe() get reference to dev structure even though i am not passing it?
If i am 100% sure that my device exists on the system, how can i call pci_enable_device() without registering?
I am currently referring LDD3 book where they explain all the calls but for a beginner i feel it misses out how to connect the dot. Does any one have pointers where widely used pci_xx() calls are explained with neat examples?
Your probe function is called by pci_register_driver, which searches for an unclaimed device with a matching device ID.
Your pci_get_device call happens after probe has returned, and is not needed.
Related
I do not know why my code does not seem to be working properly. I am reading from a file, and grabbing each line and from there I am using my own function to try and break down each of the lines and add them to character arrays in a structure and then add those structures to an array. But for whatever reason, when I am trying to indivudually print out the individual values for all of the information it keeps printing out all of it. From what I am seeing, for whatever reason even though my function strsub is supposed to add a '\0' at the end, it does not seem to be doing that. So every time I pass in the pointer to the begging of each of the character variables it does not stop until the end of the whole structure so it starts by printing out the whole string and then prints out less and less. Is that the problem that I really have or am I missing something else?
This is my code so far. I first just tried creating a struct and filling the array with each pass, but unfortunantly I had the same issue.
#define _CRT_SECURE_NO_WARNINGS // Since I want to strictly use ANSI C and not Microsoft C without getting the warning message, I'm adding this line of code before I include header files.
#include <stdio.h> // "#include" includes the contents of another file, commonly called header file, into the source code file.
#include <string.h>
#define MAX 100
FILE *fp, *csit;
void strsub(char buf[], char sub[], int start, int end);
void printArray(struct trainCartrain[]);
struct trainCar {
char car[10];
char type[2];
char weight[6];
char length[3];
char horsepower[3];
char numberInTrain[4];
};
int main() {
struct trainCar ar[7];
struct trainCar train;
// test and open input file and output file.;
if (!(fp = fopen("train.txt", "r"))) {
printf("train.txt could not be opened for input.");
exit(1);
}
if (!(csit = fopen("csit.txt", "w"))) {
printf("csit.txt could not be opened for output.");
exit(1);
}
int i = 0;
char buf[MAX];
while (!feof(fp)) {
fgets(buf, MAX, fp);
strsub(buf, train.car, 0, 9);
strsub(buf, train.type, 10, 11);
strsub(buf, train.weight, 12, 17);
strsub(buf, train.length, 18, 20);
strsub(buf, train.horsepower, 21, 23);
strsub(buf, train.numberInTrain, 24, 27);
printf("%s", train.car);
printf("%s", train.type);
ar[i] = train;
i++;
}
printArray(ar);
fclose(csit);
fclose(fp);
return 0;
}
void strsub(char buf[], char sub[], int start, int end) { //strsub () grabs a substring, sub, from a string, buf, given the start and end index within the string.
int i, j;
for (j = 0, i = start; i <= end; i++, j++) {
sub[j] = buf[i];
}
sub[j] = '\0';
//end with the null terminator character that signifies the end of a string.
}
My file is small and simple, textfile
Boxcar D 44000 55 16 45
Hopper B 23000 62 18 33
Tanker G 15000 45 30 12
Autocar A 30000 37 23 6
Livestock L 56500 50 18 19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25
and what it prints out is
Boxcar D 44000 55 16 45
D 44000 55 16 45
44000 55 16 45
55 16 45
16 45
45
Hopper B 23000 62 18 33
B 23000 62 18 33
23000 62 18 33
62 18 33
18 33
33
Tanker G 15000 45 30 12
G 15000 45 30 12
15000 45 30 12
45 30 12
30 12
12
Autocar A 30000 37 23 6
A 30000 37 23 6
30000 37 23 6
37 23 6
23 6
6
Livestock L 56500 50 18 19
L 56500 50 18 19
56500 50 18 19
50 18 19
18 19
19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25C 49300 53 22 100
Flatcar F 18000 66 15 2549300 53 22 100
Flatcar F 18000 66 15 2553 22 100
Flatcar F 18000 66 15 2522 100
Flatcar F 18000 66 15 25100
Flatcar F 18000 66 15 25Flatcar F 18000 66 15 25F 18000 66 15 2518000 66 15 2566 15 2515 2525
can someone please explain what I am doing wrong? I do have to use this function strsub for my class too.
I am just trying to get it to print out the individual charachter data and not the whole string each time. I think it is an issue with the terminating zero at the end and when I tried debugging it does not seem to be adding that for some reason. I don't know why though, if that is the problem.
strsub(buf, train.car, 0, 9); accesses train.car with index 0 till 9 in the loop and then index 10 outside, but that's already out of bounds for a char car[10];.
Solution:
Increase the size of all of your arrays by 1 to have space for the 0-terminator of the string.
Also have a look at Why is “while( !feof(file) )” always wrong? . It is not related to your problem, but you might run into that problem in the next minutes.
Instead of
while (!feof(fp)) {
fgets(buf, MAX, fp);
....
}
use
while (fgets(buf, MAX, fp)) {
....
}
You missed a space in void printArray(struct trainCartrain[]);. It should be void printArray(struct trainCar train[]); and moved to after the definition of struct trainCar.
You also have to #include <stdlib.h> to use exit(1);
Is there any way to initialize srand multiple times? I have an specific function to generate random numbers but every time i call it gives the same number. Any way to fix this?
int whoatk2() {
srand(time(NULL));
int a;
a = rand() % 50;
return a;
}
Unless you want a specific sequence, you should be calling srand once, and with a effectively arbitrary value like time(NULL). This would usually be done when your program starts.
If you call it every time you want a random number, you run the very real risk of initialising the generator with the same value each time (if you're calling it many times per second) and therefore getting the same "random" value each time.
This is the sort of thing you should be doing:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL)); // do this once
for (int i = 0; i < 10; ++i) { // do this many times
printf("%d\n", rand());
}
return 0;
}
Sample output is shown below, with the left column containing the output for the correct code above, and the right column containing the result of moving the srand call to inside the loop as you currently have (swapping the two lines that have comments above):
966271109 74846356
1059160369 74846356
1868029595 74846356
758240870 74846356
1795677958 74846356
806788680 74846356
1374271653 74846356
1658543317 74846356
1843517305 74846356
1568992484 74846356
srand is the function to initialize the pseudo-random generator with a seed, and rand is the function to get a random number from the generator...
You get the same random number repeatedly because you reinitialize the random number generator with the same seed every time you call whoatk2, which happens many times during the same second. The sequence of pseudo-random numbers returned by rand() is completely determined by the value passed to srand().
You should call srand() just once at the beginning of the program, preferably with a value that varies faster than time(NULL). You can use timespec_get(), gettimeofday() or similar:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef TIME_UTC
void random_initialize(void) {
struct timespec ts;
timespec_get(&ts, TIME_UTC);
srand(ts.tv_nsec);
}
#else
#include <sys/time.h>
void random_initialize(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
}
#endif
int whoatk2(void) {
return rand() % 50;
}
int main() {
random_initialize();
for (int i = 0; i < 20; i++) {
printf("%d ", whoatk2());
}
printf("\n");
return 0;
}
Running 10 times:
36 33 35 31 8 32 1 5 30 23 20 8 5 35 47 10 14 26 34 40
32 49 33 16 28 31 22 6 32 33 45 44 17 32 18 38 8 34 28 38
48 38 35 49 25 18 40 3 38 3 36 46 12 26 21 16 15 48 34 39
49 33 9 28 24 39 4 32 33 9 29 23 10 29 41 24 12 33 35 33
5 40 49 16 22 47 27 15 29 39 35 32 28 23 39 35 19 24 10 0
5 45 33 24 4 28 48 40 32 22 27 45 32 11 35 28 0 37 32 9
36 3 38 16 12 25 14 27 30 31 0 49 41 40 39 5 23 26 40 8
11 9 21 15 34 0 13 47 49 47 33 21 3 42 16 19 32 32 33 15
14 2 27 26 19 15 5 41 32 49 48 31 20 12 39 16 15 19 32 20
3 2 34 32 47 24 34 21 0 28 6 48 44 16 6 46 40 48 20 13
I have the following issue: I want to define the clock a CPU should use during frequency transitions in the device tree rather than in the clock driver code (in this way it will be more generic). I want to define the "transition-clock" property in the device tree, something like:
232 cpu: cpu#01c20050 {
233 #clock-cells = <0>;
234 compatible = "allwinner,sun4i-a10-cpu-clk";
235 reg = <0x01c20050 0x4>;
-----
243 clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
244 transition-clock = <&osc24M>;
245 clock-output-names = "cpu";
246 };
I changed the file "drivers/clk/clkdev.c" to search this property so I can get a clk pointer and store it in a new property in the cpu clock structure. This is what I have managed so far (changes begin on line 78):
59 static struct clk *__of_clk_get(struct device_node *np, int index,
60 const char *dev_id, const char *con_id)
61 {
62 struct of_phandle_args clkspec;
63 struct clk *clk, *transition_clk;
64 struct device_node *clock_node, *transition_clock_node;
65 int rc;
66
67 if (index < 0)
68 return ERR_PTR(-EINVAL);
69
70 rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
71 &clkspec);
72 if (rc)
73 return ERR_PTR(rc);
74
75 clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
76 of_node_put(clkspec.np);
77
78 clock_node = of_parse_phandle(np, "clocks", 0);
79 pr_err("-------------------- parsing node %s\n", np->name);
80 if (clock_node!=NULL) {
81 pr_err("============ Clock node found %p\n", clock_node);
82 transition_clock_node =
83 of_parse_phandle(clock_node, "transition-clock", 0);
84 if (transition_clock_node!=NULL) {
85 pr_err("============ Transition clock node found %p\n",
86 transition_clock_node);
87 transition_clk = clk_get(clock_node, 0);
88 pr_err("============ Transition clock %p\n", transition_clk);
89 }
90 }
91
92 return clk;
93 }
I get pointers to the clock node and the transition clock node, but when I try to get a clock pointer from that, I get 0xfffffffe, which looks like an error:
[ 2.540542] -------------------- parsing node cpu
[ 2.540546] ============ Clock node found eeef9520
[ 2.540550] ============ Transition clock node found eeef8934
[ 2.540555] ============ Transition clock fffffffe
I want a clock object which I can later use in
clk_set_parent(cpu_clk, cpu_clk->transition_clk)
Any ideas are welcome :)
OK, I got it figured out in the meantime and since nobody answered I'm going to provide my solution (maybe somebody else bumps into this issue):
81 if (clock_node != NULL) {
82 rc = of_parse_phandle_with_args(clock_node, "transition-clock", NULL,
83 0, &transition_clkspec);
84 of_node_put(transition_clkspec.np);
85
86 if (!rc) {
87 transition_clock = __of_clk_get_by_clkspec(&transition_clkspec,
88 dev_id, con_id);
89 clk_set_transition_parent(clk, transition_clock);
90 }
91 }
So, the solution is to get an object of type "of_phandle_args" and get the clock from there using __of_clk_get_by_clkspec.
(the clk_set_transition_parent function is defined somewhere else and it does exactly what it's name suggests)
I'm using bufbomb.c to do some buffer overflow attack experimenting.
I successfully used gdb to debug the code. Howeverer; when I run the program directly, I get a "Segmentation fault (core dumped)" when I enter the characters to try the attack.
I used gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1. to build the following.
//bufbomb.c
/* Bomb program that is solved using a buffer overflow attack */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char *getxs(char *dest)
{
int c;
int even =1; /* Have read even number of digits */
int otherd =0; /* Other hex digit of pair */
char*sp = dest;
while ((c = getchar()) != EOF && c !='\n') {
if (isxdigit(c)) {
int val;
if ('0'<= c && c <='9')
val = c -'0';
else if ('A'<= c && c <='F')
val = c -'A'+10;
else
val = c -'a'+10;
if (even) {
otherd = val;
even =0;
}
else {
*sp++= otherd *16+ val;
even =1;
}
}
}
*sp++='\0';
return dest;
}
/* $begin getbuf-c */
int getbuf()
{
char buf[12];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
/* $end getbuf-c */
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) &0xFFF);
int*space = (int*) alloca(offset);
*space =0; /* So that don't get complaint of unused variable */
test();
return 0;
}
Then I executed it under gdb:
...> gdb ./bugbomb
...
..run
Type Hex string:30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 d8 bf ff ff 9f 85 04 08 b0 86 04 08 30 31 32 33 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ef be ad de
getbuf returned 0xdeadbeef
[Inferior 1 (process 13530) exited normally]
And then without gdb::
./bufbomb
Type Hex string:30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 d8 bf ff ff 9f 85 04 08 b0 86 04 08 30 31 32 33 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 ef be ad de
Segmentation fault (core dumped)
I am looking for some help to resolve the seg-fault.
Run it under gdb with a bigger buffer to see which address it's trying to access to guess the stack offset of the return address used by getbuf().
To bear with small differences in memory offsets that arise from the use of gdb, use a NOP-sled. Your attack buffer should look like this:
|RET ADDRESS x 30 | NOPS (0x90) x 1000 | SHELLCODE|.
The return address should point to the middle of the NOP-sled.
If the execution jumps anywhere in the sled, it will slide to the shellcode.
You are accessing memory that your process doesn't "own".
When you run gdb, the compiler adds stuff (like extra debug info).
You can bypass the segmentation fault by expanding the stack before you attempt the buffer overflow:
int expand_stack(int n_bytes)
{
char buf[n_bytes];
return buf[n_bytes-1]; // access the memory to make sure the optimiser doesn't remove buf.
}
And in main, add a call to expand_stack before you call test:
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int) buf) &0xFFF);
int*space = (int*) alloca(offset);
*space = expand_stack(200);
test();
return 0;
}
Note that your code still invokes undefined behaviour.
Note2: If your compiler doesn't support variable length arrays, just use a fixed array, buf[200].
When I use pthread in cocoa, and want to access cocoa control in pthread function(setBtnState), it doesn't work. What's the problem?
The following is the source code:
AppController.h
1 //
2 // AppController.h
3 // PThreadTest
4 //
5 // Created by zhu on 10-9-5.
6 // Copyright 2010 __MyCompanyName__. All rights reserved.
7 //
8
9 #import <Cocoa/Cocoa.h>
10
11
12 #interface AppController : NSObject {
13 IBOutlet NSButton *btnNew;
14 IBOutlet NSButton *btnEnd;
15 }
16
17 -(IBAction)newThread:(id)sender;
18 -(IBAction)endThread:(id)sender;
19
20 #end
AppController.m
1 //
2 // AppController.m
3 // PThreadTest
4 //
5 // Created by zhu on 10-9-5.
6 // Copyright 2010 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "AppController.h"
10 #import <pthread.h>
11
12
13 #implementation AppController
14
15 struct mydata {
16 pthread_mutex_t mutex;
17 pthread_cond_t cond;
18 int stop;
19 NSButton *btnNew;
20 NSButton *btnEnd;
21 };
22
23 struct mydata adata;
24 struct mydata *ptr;
25
26 void setBtnState(struct mydata *p) {
27 BOOL stop = NO;
28 if (p->stop) {
29 stop = YES;
30 }
31 [p->btnNew setEnabled:stop];
32 [p->btnEnd setEnabled:!stop];
33 }
34
35 void* mythread(void* arg) {
36 NSLog(#"new thread start...");
37 ptr->stop = 0;
38 setBtnState(ptr);
39 pthread_mutex_lock(&ptr->mutex);
40 while (!ptr->stop) {
41 pthread_cond_wait(&ptr->cond, &ptr->mutex);
42 }
43 pthread_mutex_unlock(&ptr->mutex);
44 setBtnState(ptr);
45 NSLog(#"current thread end...");
46 }
47
48 -(id)init {
49 self = [super init];
50 ptr = &adata;
51 pthread_mutex_init(&ptr->mutex, NULL);
52 pthread_cond_init(&ptr->cond, NULL);
53 ptr->stop = 0;
54 ptr->btnNew = btnNew;
55 ptr->btnEnd = btnEnd;
56 return self;
57 }
58
59 -(IBAction)newThread:(id)sender {
60 pthread_t pid;
61 pthread_create(&pid, NULL, mythread, NULL);
62 }
63
64 -(IBAction)endThread:(id)sender {
65 pthread_mutex_lock(&ptr->mutex);
66 ptr->stop = 1;
67 pthread_mutex_unlock(&ptr->mutex);
68 pthread_cond_signal(&ptr->cond);
69 }
70
71 #end
Thanks to Chris. In the backgroud thread in order to update control's state I use performSelectorOnMainThread to communicate with the main UI thread.
But when btnEnd is pressed, the debugger console show the following infomation:
2010-09-12 23:36:29.255 PThreadTest[1888:a0f] -[AppController setBtnState]: unrecognized selector sent to instance 0x100133030
Why it doesn't work after I updated AppController.m as the following:
1 //
2 // AppController.m
3 // PThreadTest
4 //
5 // Created by zhu on 10-9-5.
6 // Copyright 2010 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "AppController.h"
10 #import <pthread.h>
11
12
13 #implementation AppController
14
15 struct mydata {
16 pthread_mutex_t mutex;
17 pthread_cond_t cond;
18 int stop;
19 NSButton *btnNew;
20 NSButton *btnEnd;
21 id obj;
22 };
23
24 struct mydata adata;
25 struct mydata *ptr;
26
27 void* mythread(void* arg) {
28 NSLog(#"new thread start...");
29 ptr->stop = 0;
30 pthread_mutex_lock(&ptr->mutex);
31 while (!ptr->stop) {
32 pthread_cond_wait(&ptr->cond, &ptr->mutex);
33 }
34 pthread_mutex_unlock(&ptr->mutex);
35 [ptr->obj performSelectorOnMainThread:#selector(setBtnState) withObject:#"YES" waitUntilDone:NO];
36 NSLog(#"current thread end...");
37 }
38
39 -(void)setBtnState:(id)aobj {
40 BOOL stop = NO;
41 if ([aobj isEqualToString:#"YES"]) {
42 stop = YES;
43 }
44 [btnNew setEnabled:stop];
45 [btnEnd setEnabled:!stop];
46 }
47
48 -(id)init {
49 self = [super init];
50 ptr = &adata;
51 pthread_mutex_init(&ptr->mutex, NULL);
52 pthread_cond_init(&ptr->cond, NULL);
53 ptr->stop = 0;
54 ptr->obj = self;
55 // ptr->btnNew = btnNew;
56 // ptr->btnEnd = btnEnd;
57 return self;
58 }
59
60 - (void)awakeFromNib {
61 ptr->btnNew = btnNew;
62 ptr->btnEnd = btnEnd;
63 }
64
65 -(IBAction)newThread:(id)sender {
66 [self setBtnState:#"NO"];
67 pthread_t pid;
68 pthread_create(&pid, NULL, mythread, NULL);
69 }
70
71 -(IBAction)endThread:(id)sender {
72 pthread_mutex_lock(&ptr->mutex);
73 ptr->stop = 1;
74 pthread_mutex_unlock(&ptr->mutex);
75 pthread_cond_signal(&ptr->cond);
76 }
77
78 #end
79
You should only interact with your UI from the main thread, not from background threads.
This isn't just a matter of locking around interaction with your own controls; your controls may interact with other objects in the UI behind your back. (For example, your button may interact with your window.) This can lead to race conditions, deadlocks, invalid/mixed state, and other concurrency problems.
When you're doing some processing work on a background thread, and it needs to communicate results (whether intermediate or final) to the user, it will need to push that communication through the main thread. There are a few mechanisms in Cocoa with which to do this:
The -performSelectorOnMainThread:withObject:waitUntilDone: method lets you say "run this other method on the main thread," optionally waiting until it's done. You should almost never pass YES for the waitUntilDone: argument though, as that's a recipe for deadlock.
Starting in Mac OS X 10.6 and iOS 4.0, there is +[NSOperationQueue mainQueue], which returns an instance of NSOperationQueue associated with the main thread: You can place operations on this queue and they will run on the main thread.
This is useful if you're using several operations on a background queue and you have some "finishing" operation to perform on the main thread that depends on all of them. You can just use NSOperation's dependency mechanism to set up dependencies between them even though they're on different queues.
You can either subclass NSOperation or use Objective-C blocks for the bodies of your operations (via +[NSBlockOperation blockOperationWithBock:]).
Also starting in Mac OS X 10.6 and iOS 4.0, there is Grand Central Dispatch which lets you perform a block on a main queue associated with the main thread. It's a slightly less verbose API than NSOperation, but at the cost of not having direct support for dependencies and some of the other features of NSOperationQueue, and of being built in plain C rather than in Objective-C.
One thing to remember when using any of these mechanisms is that you must not interact with the same data from multiple threads at the same time without appropriate concurrency control (such as locking, or the use of specialized lock-free data structures and primitives). You can't get away with "Oh, I'm just reading, so I don't need to take a lock," or "Oh, I just need to enable a button, I don't really need to push that to the main thread."
A good way to avoid this issue is to do as much work as possible by batching it up into discrete units, processing those units in the background, and then relaying the results to the main thread.
So your threaded code is not written like this:
spin off a thread to:
lock the document
get some data from the document
unlock the document
process the data
tell the main thread whether to enable or disable the document's Foo button
Instead your threaded code is written like this:
get some data from the document
spin off a thread to:
process the data
then tell the main thread the result of the processing
on the main thread:
determine from the result of the processing whether to enable or disable the document's Foo button
The difference is that the latter is written in terms of the units of work being done, rather than in terms of the user interface, and will be both easier to understand and more robust in the face of your application's life (such as adding features) - it's essentially "MVC applied to threads."
You want to move:
ptr->btnNew = btnNew;
ptr->btnEnd = btnEnd;
... to awakeFromNib if you are using outlets and loading from a nib file. There is no guarantee that the outlets will be resolved until awakeFromNib is called and init is called before awakeFromNib.
I'm not certain you can use pthreads to communicate with the UI. I'm pretty sure you have to use NSThread and notifications to talk to controls on the main thread.