По первому - что подразумевается под "userspace" ?
По второму - передавай соответствующие структуры данных разным потокам при инициализации. Есть два варианта:
1. Ты делаешь разные поточные функции - каждая выполняет свою обработку. В таком случае описываешь разные структуры и передаешь их каждую своей функции;
2. Ты делаешь одну большую функцию обработки, в которой как-то определяешь, что нужно сделать и делаешь. В таком случае кроме описания разных структур описываешь еще одну структуру примерно такую:
struct xxx {
int code;
void *data;
};
где code - признак исполняемой задачи (лучше всего в enum их записать и потом по switch выбирать), data - ссылка на структуру данных для этой задачи. В таком случае при создании потока ты передаешь ему структуру xxx, записав в поле code код задачи и в поле data адрес структуры для этой задачи. В потоке выполняется что-то типа:
switch (param->code) {
case TAST_TYPE1: struct yyy *data=(struct yyy *)param->data;
// выпоняется задача 1-го типа с данными в стуркуре data (struct yyy)
..........
break;
case TAST_TYPE2: struct zzz *data=(struct yyy *)param->data;
// выпоняется задача 2-го типа с данными в стуркуре data (struct zzz)
..........
break;
............
};