Commit 698e9069 authored by Christoffer Ackelman's avatar Christoffer Ackelman

Merged OS-specific files since they were nearly identical.

parent 43c980a2
...@@ -115,7 +115,11 @@ pwr_tStatus syi_UserName(char* user, int len) ...@@ -115,7 +115,11 @@ pwr_tStatus syi_UserName(char* user, int len)
{ {
char* p; char* p;
#if defined(OS_CYGWIN) || defined(OS_LINUX)
p = cuserid(0); p = cuserid(0);
#else
p = getlogin();
#endif
if (!p) if (!p)
return 0; return 0;
strncpy(user, p, len); strncpy(user, p, len);
...@@ -137,15 +141,18 @@ const char* syi_Hardware() ...@@ -137,15 +141,18 @@ const char* syi_Hardware()
const char* syi_OpSys() const char* syi_OpSys()
{ {
#if defined OS_LINUX #if defined OS_LINUX
static const char opsys[] = "Linux"; return "Linux";
#elif defined OS_MACOS #elif defined OS_MACOS
static const char opsys[] = "MacOS"; return "MacOS";
#elif defined OS_FREEBSD #elif defined OS_FREEBSD
static const char opsys[] = "FreeBSD"; return "FreeBSD";
#elif defined OS_OPENBSD
return "OpenBSD";
#elif defined OS_CYGWIN
return "Cygwin";
#else #else
static const char opsys[] = "Unknown"; return "Unknown";
#endif #endif
return opsys;
} }
char* syi_ProcessId() char* syi_ProcessId()
......
...@@ -37,10 +37,6 @@ ...@@ -37,10 +37,6 @@
/* co_time_os.c -- OS specific time routines. /* co_time_os.c -- OS specific time routines.
*/ */
#ifndef OS_LINUX
#error This file is only for Linux
#endif
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/times.h> #include <sys/times.h>
......
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_syi.c -- System information
This module gives information about the system. */
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "co_syi.h"
#include "co_syi_msg.h"
char* syi_HostName(pwr_tStatus* status, char* ibuffer, int isize)
{
return syi_NodeName(status, ibuffer, isize);
}
char* syi_NodeName(pwr_tStatus* status, char* ibuffer, int isize)
{
char* cp;
pwr_dStatus(sts, status, SYI__SUCCESS);
if (gethostname(ibuffer, isize) != 0) {
if (errno == EINVAL) {
*sts = SYI__TRUNCATED;
} else {
*sts = errno_Status(errno);
ibuffer = NULL;
}
}
/* Remove domain */
if ((cp = strchr(ibuffer, '.')))
*cp = 0;
return ibuffer;
}
char* syi_Ethernet(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_NodeSpec(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_HostSpec(pwr_tStatus* status, char* ibuffer, int size)
{
return syi_NodeSpec(status, ibuffer, size);
}
/* Return true if node is booted locally or
false if booted from remote node via network. */
pwr_tBoolean syi_LocalBoot(pwr_tStatus* status)
{
return YES;
}
/* . */
char* syi_BootDisk(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
pwr_tStatus syi_UserName(char* user, int len)
{
char* p;
p = cuserid(0);
if (!p)
return 0;
strncpy(user, p, len);
return 1;
}
const char* syi_Hardware()
{
#if defined HW_X86_64
static const char hw[] = "x86_64";
#elif defined HW_ARM
static const char hw[] = "ARM";
#else
static const char hw[] = "x86";
#endif
return hw;
}
const char* syi_OpSys()
{
#if defined OS_LINUX
static const char opsys[] = "Linux";
#elif defined OS_MACOS
static const char opsys[] = "MacOS";
#elif defined OS_FREEBSD
static const char opsys[] = "FreeBSD";
#elif defined OS_OPENBSD
static const char opsys[] = "OpenBSD";
#elif defined OS_CYGWIN
static const char opsys[] = "Cygwin";
#else
static const char opsys[] = "Unknown";
#endif
return opsys;
}
char* syi_ProcessId()
{
static char pidstr[40];
sprintf(pidstr, "%u", getpid());
return pidstr;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_time_os.c -- OS specific time routines.
*/
#ifndef OS_CYGWIN
#error This file is only for Cygwin
#endif
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include "co_time.h"
#include "co_time_msg.h"
/* Modified to keep uptime tics as a 64-bit unsigned.
* This way uptime tics won't wrap around for another 8000 years or so
* when HZ is at a 1000.
* RK 031112
*/
pwr_tDeltaTime* time_Uptime(
pwr_tStatus* status, pwr_tDeltaTime* tp, pwr_tDeltaTime* ap)
{
pwr_tDeltaTime time;
unsigned long tics;
static pwr_tUInt64 tics_64;
struct tms buff;
static int tics_per_sec = 0;
static pwr_tTime boot_time = { 0, 0 };
static pwr_tDeltaTime max_diff = { 0, 20000000 };
pwr_tDeltaTime uptime_tics;
pwr_tTime current_time;
pwr_tDeltaTime diff;
static pwr_tUInt16 msb_flips = 0;
static pwr_tBoolean old_high_bit = 0;
pwr_tBoolean high_bit;
lldiv_t uptime_s;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
if (tp == NULL)
tp = &time;
tics = times(&buff);
high_bit = tics >> (32 - 1);
if (!high_bit && old_high_bit)
msb_flips++;
old_high_bit = high_bit;
tics_64 = ((pwr_tUInt64)msb_flips << 32) | tics;
uptime_s = lldiv(tics_64, (pwr_tInt64)tics_per_sec);
uptime_tics.tv_sec = (pwr_tInt64)uptime_s.quot;
uptime_tics.tv_nsec
= ((pwr_tUInt64)uptime_s.rem) * (1000000000 / tics_per_sec);
// pwr_Assert(tp->tv_sec >= 0 && tp->tv_nsec >= 0);
time_GetTime(&current_time);
if (!boot_time.tv_sec) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
} else {
time_Adiff(tp, &current_time, &boot_time);
time_Dsub(&diff, tp, &uptime_tics);
time_Dabs(NULL, &diff);
if (time_Dcomp(&diff, &max_diff) > 0) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
if (status != NULL) {
*status = TIME__CLKCHANGE;
}
}
}
if (ap != NULL)
return time_Dadd(tp, tp, ap);
else
return tp;
}
/* Return number of clock ticks since system start.
Add number of tics corresponding to delta time 'add'. */
time_tClock time_Clock(pwr_tStatus* status, pwr_tDeltaTime* ap)
{
long tics;
struct tms buff;
static int tics_per_sec = 0;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
tics = times(&buff);
if (ap != NULL) {
tics += (ap->tv_sec * tics_per_sec)
+ (ap->tv_nsec / (1000000000 / tics_per_sec));
}
return tics;
}
time_tOs* time_Os(pwr_tStatus* status, time_tOs* tp)
{
static time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
time_GetTime(tp);
return tp;
}
/* Set system time */
pwr_tStatus time_SetTime(pwr_tTime* pt)
{
pwr_tStatus sts = TIME__SUCCESS;
return sts;
}
time_tOs* time_AtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tTime* ap)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
*tp = *ap;
return tp;
}
/* Convert from Proview delta time format
to native time format. */
time_tOs* time_DtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tDeltaTime* dp)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
memcpy(tp, dp, sizeof(*tp));
return tp;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_syi.c -- System information
This module gives information about the system. */
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "co_syi.h"
#include "co_syi_msg.h"
char* syi_HostName(pwr_tStatus* status, char* ibuffer, int isize)
{
return syi_NodeName(status, ibuffer, isize);
}
char* syi_NodeName(pwr_tStatus* status, char* ibuffer, int isize)
{
char* cp;
pwr_dStatus(sts, status, SYI__SUCCESS);
if (gethostname(ibuffer, isize) != 0) {
if (errno == EINVAL) {
*sts = SYI__TRUNCATED;
} else {
*sts = errno_Status(errno);
ibuffer = NULL;
}
}
/* Remove domain */
if ((cp = strchr(ibuffer, '.')))
*cp = 0;
return ibuffer;
}
char* syi_Ethernet(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_NodeSpec(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_HostSpec(pwr_tStatus* status, char* ibuffer, int size)
{
return syi_NodeSpec(status, ibuffer, size);
}
/* Return true if node is booted locally or
false if booted from remote node via network. */
pwr_tBoolean syi_LocalBoot(pwr_tStatus* status)
{
return YES;
}
/* . */
char* syi_BootDisk(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
pwr_tStatus syi_UserName(char* user, int len)
{
char* p;
p = getlogin();
if (!p)
return 0;
strncpy(user, p, len);
return 1;
}
const char* syi_Hardware()
{
#if defined HW_X86_64
static const char hw[] = "x86_64";
#else
static const char hw[] = "x86";
#endif
return hw;
}
const char* syi_OpSys()
{
#if defined OS_LINUX
static const char opsys[] = "Linux";
#elif defined OS_MACOS
static const char opsys[] = "MacOS";
#elif defined OS_FREEBSD
static const char opsys[] = "FreeBSD";
#else
static const char opsys[] = "Unknown";
#endif
return opsys;
}
char* syi_ProcessId()
{
static char pidstr[40];
sprintf(pidstr, "%u", getpid());
return pidstr;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_time_os.c -- OS specific time routines.
*/
#ifndef OS_FREEBSD
#error This file is only for FreeBSD
#endif
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include "co_time.h"
#include "co_time_msg.h"
/* Modified to keep uptime tics as a 64-bit unsigned.
* This way uptime tics won't wrap around for another 8000 years or so
* when HZ is at a 1000.
* RK 031112
*/
pwr_tDeltaTime* time_Uptime(
pwr_tStatus* status, pwr_tDeltaTime* tp, pwr_tDeltaTime* ap)
{
pwr_tDeltaTime time;
unsigned long tics;
static pwr_tUInt64 tics_64;
struct tms buff;
static int tics_per_sec = 0;
static pwr_tTime boot_time = { 0, 0 };
static pwr_tDeltaTime max_diff = { 0, 20000000 };
pwr_tDeltaTime uptime_tics;
pwr_tTime current_time;
pwr_tDeltaTime diff;
static pwr_tUInt16 msb_flips = 0;
static pwr_tBoolean old_high_bit = 0;
pwr_tBoolean high_bit;
lldiv_t uptime_s;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
if (tp == NULL)
tp = &time;
tics = times(&buff);
high_bit = tics >> (32 - 1);
if (!high_bit && old_high_bit)
msb_flips++;
old_high_bit = high_bit;
tics_64 = ((pwr_tUInt64)msb_flips << 32) | tics;
uptime_s = lldiv(tics_64, (pwr_tInt64)tics_per_sec);
uptime_tics.tv_sec = (pwr_tInt64)uptime_s.quot;
uptime_tics.tv_nsec
= ((pwr_tUInt64)uptime_s.rem) * (1000000000 / tics_per_sec);
// pwr_Assert(tp->tv_sec >= 0 && tp->tv_nsec >= 0);
time_GetTime(&current_time);
if (!boot_time.tv_sec) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
} else {
time_Adiff(tp, &current_time, &boot_time);
time_Dsub(&diff, tp, &uptime_tics);
time_Dabs(NULL, &diff);
if (time_Dcomp(&diff, &max_diff) > 0) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
if (status != NULL) {
*status = TIME__CLKCHANGE;
}
}
}
if (ap != NULL)
return time_Dadd(tp, tp, ap);
else
return tp;
}
/* Return number of clock ticks since system start.
Add number of tics corresponding to delta time 'add'. */
time_tClock time_Clock(pwr_tStatus* status, pwr_tDeltaTime* ap)
{
long tics;
struct tms buff;
static int tics_per_sec = 0;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
tics = times(&buff);
if (ap != NULL) {
tics += (ap->tv_sec * tics_per_sec)
+ (ap->tv_nsec / (1000000000 / tics_per_sec));
}
return tics;
}
time_tOs* time_Os(pwr_tStatus* status, time_tOs* tp)
{
static time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
time_GetTime(tp);
return tp;
}
/* Set system time */
pwr_tStatus time_SetTime(pwr_tTime* pt)
{
pwr_tStatus sts = TIME__SUCCESS;
return sts;
}
time_tOs* time_AtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tTime* ap)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
*tp = *ap;
return tp;
}
/* Convert from Proview delta time format
to native time format. */
time_tOs* time_DtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tDeltaTime* dp)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
memcpy(tp, dp, sizeof(*tp));
return tp;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_syi.c -- System information
This module gives information about the system. */
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "co_syi.h"
#include "co_syi_msg.h"
char* syi_HostName(pwr_tStatus* status, char* ibuffer, int isize)
{
return syi_NodeName(status, ibuffer, isize);
}
char* syi_NodeName(pwr_tStatus* status, char* ibuffer, int isize)
{
char* cp;
pwr_dStatus(sts, status, SYI__SUCCESS);
if (gethostname(ibuffer, isize) != 0) {
if (errno == EINVAL) {
*sts = SYI__TRUNCATED;
} else {
*sts = errno_Status(errno);
ibuffer = NULL;
}
}
/* Remove domain */
if ((cp = strchr(ibuffer, '.')))
*cp = 0;
return ibuffer;
}
char* syi_Ethernet(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_NodeSpec(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_HostSpec(pwr_tStatus* status, char* ibuffer, int size)
{
return syi_NodeSpec(status, ibuffer, size);
}
/* Return true if node is booted locally or
false if booted from remote node via network. */
pwr_tBoolean syi_LocalBoot(pwr_tStatus* status)
{
return YES;
}
/* . */
char* syi_BootDisk(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
pwr_tStatus syi_UserName(char* user, int len)
{
char* p;
p = getlogin();
if (!p)
return 0;
strncpy(user, p, len);
return 1;
}
const char* syi_Hardware()
{
#if defined HW_X86_64
static const char hw[] = "x86_64";
#else
static const char hw[] = "x86";
#endif
return hw;
}
const char* syi_OpSys()
{
#if defined OS_LINUX
static const char opsys[] = "Linux";
#elif defined OS_MACOS
static const char opsys[] = "MacOS";
#else
static const char opsys[] = "Unknown";
#endif
return opsys;
}
char* syi_ProcessId()
{
static char pidstr[40];
sprintf(pidstr, "%u", getpid());
return pidstr;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_time_os.c -- OS specific time routines.
*/
#ifndef OS_MACOS
#error This file is only for Mac OS
#endif
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include "co_time.h"
#include "co_time_msg.h"
/* Modified to keep uptime tics as a 64-bit unsigned.
* This way uptime tics won't wrap around for another 8000 years or so
* when HZ is at a 1000.
* RK 031112
*/
pwr_tDeltaTime* time_Uptime(
pwr_tStatus* status, pwr_tDeltaTime* tp, pwr_tDeltaTime* ap)
{
pwr_tDeltaTime time;
unsigned long tics;
static pwr_tUInt64 tics_64;
struct tms buff;
static int tics_per_sec = 0;
static pwr_tTime boot_time = { 0, 0 };
static pwr_tDeltaTime max_diff = { 0, 20000000 };
pwr_tDeltaTime uptime_tics;
pwr_tTime current_time;
pwr_tDeltaTime diff;
static pwr_tUInt16 msb_flips = 0;
static pwr_tBoolean old_high_bit = 0;
pwr_tBoolean high_bit;
lldiv_t uptime_s;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
if (tp == NULL)
tp = &time;
tics = times(&buff);
high_bit = tics >> (32 - 1);
if (!high_bit && old_high_bit)
msb_flips++;
old_high_bit = high_bit;
tics_64 = ((pwr_tUInt64)msb_flips << 32) | tics;
uptime_s = lldiv(tics_64, (pwr_tInt64)tics_per_sec);
uptime_tics.tv_sec = (pwr_tInt64)uptime_s.quot;
uptime_tics.tv_nsec
= ((pwr_tUInt64)uptime_s.rem) * (1000000000 / tics_per_sec);
// pwr_Assert(tp->tv_sec >= 0 && tp->tv_nsec >= 0);
time_GetTime(&current_time);
if (!boot_time.tv_sec) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
} else {
time_Adiff(tp, &current_time, &boot_time);
time_Dsub(&diff, tp, &uptime_tics);
time_Dabs(NULL, &diff);
if (time_Dcomp(&diff, &max_diff) > 0) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
if (status != NULL) {
*status = TIME__CLKCHANGE;
}
}
}
if (ap != NULL)
return time_Dadd(tp, tp, ap);
else
return tp;
}
/* Return number of clock ticks since system start.
Add number of tics corresponding to delta time 'add'. */
time_tClock time_Clock(pwr_tStatus* status, pwr_tDeltaTime* ap)
{
long tics;
struct tms buff;
static int tics_per_sec = 0;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
tics = times(&buff);
if (ap != NULL) {
tics += (ap->tv_sec * tics_per_sec)
+ (ap->tv_nsec / (1000000000 / tics_per_sec));
}
return tics;
}
time_tOs* time_Os(pwr_tStatus* status, time_tOs* tp)
{
static time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
time_GetTime(tp);
return tp;
}
/* Set system time */
pwr_tStatus time_SetTime(pwr_tTime* pt)
{
pwr_tStatus sts = TIME__SUCCESS;
return sts;
}
time_tOs* time_AtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tTime* ap)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
*tp = *ap;
return tp;
}
/* Convert from Proview delta time format
to native time format. */
time_tOs* time_DtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tDeltaTime* dp)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
memcpy(tp, dp, sizeof(*tp));
return tp;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_syi.c -- System information
This module gives information about the system. */
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "co_syi.h"
#include "co_syi_msg.h"
char* syi_HostName(pwr_tStatus* status, char* ibuffer, int isize)
{
return syi_NodeName(status, ibuffer, isize);
}
char* syi_NodeName(pwr_tStatus* status, char* ibuffer, int isize)
{
char* cp;
pwr_dStatus(sts, status, SYI__SUCCESS);
if (gethostname(ibuffer, isize) != 0) {
if (errno == EINVAL) {
*sts = SYI__TRUNCATED;
} else {
*sts = errno_Status(errno);
ibuffer = NULL;
}
}
/* Remove domain */
if ((cp = strchr(ibuffer, '.')))
*cp = 0;
return ibuffer;
}
char* syi_Ethernet(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_NodeSpec(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_HostSpec(pwr_tStatus* status, char* ibuffer, int size)
{
return syi_NodeSpec(status, ibuffer, size);
}
/* Return true if node is booted locally or
false if booted from remote node via network. */
pwr_tBoolean syi_LocalBoot(pwr_tStatus* status)
{
return YES;
}
/* . */
char* syi_BootDisk(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
pwr_tStatus syi_UserName(char* user, int len)
{
char* p;
p = getlogin();
if (!p)
return 0;
strncpy(user, p, len);
return 1;
}
const char* syi_Hardware()
{
#if defined HW_X86_64
static const char hw[] = "x86_64";
#else
static const char hw[] = "x86";
#endif
return hw;
}
const char* syi_OpSys()
{
#if defined OS_LINUX
static const char opsys[] = "Linux";
#elif defined OS_MACOS
static const char opsys[] = "MacOS";
#elif defined OS_FREEBSD
static const char opsys[] = "FreeBSD";
#elif defined OS_OPENBSD
static const char opsys[] = "OpenBSD";
#else
static const char opsys[] = "Unknown";
#endif
return opsys;
}
char* syi_ProcessId()
{
static char pidstr[40];
sprintf(pidstr, "%u", getpid());
return pidstr;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_time_os.c -- OS specific time routines.
*/
#ifndef OS_OPENBSD
#error This file is only for OpenBSD
#endif
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include "co_time.h"
#include "co_time_msg.h"
/* Modified to keep uptime tics as a 64-bit unsigned.
* This way uptime tics won't wrap around for another 8000 years or so
* when HZ is at a 1000.
* RK 031112
*/
pwr_tDeltaTime* time_Uptime(
pwr_tStatus* status, pwr_tDeltaTime* tp, pwr_tDeltaTime* ap)
{
pwr_tDeltaTime time;
unsigned long tics;
static pwr_tUInt64 tics_64;
struct tms buff;
static int tics_per_sec = 0;
static pwr_tTime boot_time = { 0, 0 };
static pwr_tDeltaTime max_diff = { 0, 20000000 };
pwr_tDeltaTime uptime_tics;
pwr_tTime current_time;
pwr_tDeltaTime diff;
static pwr_tUInt16 msb_flips = 0;
static pwr_tBoolean old_high_bit = 0;
pwr_tBoolean high_bit;
lldiv_t uptime_s;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
if (tp == NULL)
tp = &time;
tics = times(&buff);
high_bit = tics >> (32 - 1);
if (!high_bit && old_high_bit)
msb_flips++;
old_high_bit = high_bit;
tics_64 = ((pwr_tUInt64)msb_flips << 32) | tics;
uptime_s = lldiv(tics_64, (pwr_tInt64)tics_per_sec);
uptime_tics.tv_sec = (pwr_tInt64)uptime_s.quot;
uptime_tics.tv_nsec
= ((pwr_tUInt64)uptime_s.rem) * (1000000000 / tics_per_sec);
// pwr_Assert(tp->tv_sec >= 0 && tp->tv_nsec >= 0);
time_GetTime(&current_time);
if (!boot_time.tv_sec) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
} else {
time_Adiff(tp, &current_time, &boot_time);
time_Dsub(&diff, tp, &uptime_tics);
time_Dabs(NULL, &diff);
if (time_Dcomp(&diff, &max_diff) > 0) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
if (status != NULL) {
*status = TIME__CLKCHANGE;
}
}
}
if (ap != NULL)
return time_Dadd(tp, tp, ap);
else
return tp;
}
/* Return number of clock ticks since system start.
Add number of tics corresponding to delta time 'add'. */
time_tClock time_Clock(pwr_tStatus* status, pwr_tDeltaTime* ap)
{
long tics;
struct tms buff;
static int tics_per_sec = 0;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
tics = times(&buff);
if (ap != NULL) {
tics += (ap->tv_sec * tics_per_sec)
+ (ap->tv_nsec / (1000000000 / tics_per_sec));
}
return tics;
}
time_tOs* time_Os(pwr_tStatus* status, time_tOs* tp)
{
static time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
time_GetTime(tp);
return tp;
}
/* Set system time */
pwr_tStatus time_SetTime(pwr_tTime* pt)
{
pwr_tStatus sts = TIME__SUCCESS;
return sts;
}
time_tOs* time_AtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tTime* ap)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
*tp = *ap;
return tp;
}
/* Convert from Proview delta time format
to native time format. */
time_tOs* time_DtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tDeltaTime* dp)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
memcpy(tp, dp, sizeof(*tp));
return tp;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_syi.c -- System information
This module gives information about the system. */
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "co_syi.h"
#include "co_syi_msg.h"
char* syi_HostName(pwr_tStatus* status, char* ibuffer, int isize)
{
return syi_NodeName(status, ibuffer, isize);
}
char* syi_NodeName(pwr_tStatus* status, char* ibuffer, int isize)
{
char* cp;
pwr_dStatus(sts, status, SYI__SUCCESS);
if (gethostname(ibuffer, isize) != 0) {
if (errno == EINVAL) {
*sts = SYI__TRUNCATED;
} else {
*sts = errno_Status(errno);
ibuffer = NULL;
}
}
/* Remove domain */
if ((cp = strchr(ibuffer, '.')))
*cp = 0;
return ibuffer;
}
char* syi_Ethernet(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_NodeSpec(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
char* syi_HostSpec(pwr_tStatus* status, char* ibuffer, int size)
{
return syi_NodeSpec(status, ibuffer, size);
}
/* Return true if node is booted locally or
false if booted from remote node via network. */
pwr_tBoolean syi_LocalBoot(pwr_tStatus* status)
{
return YES;
}
/* . */
char* syi_BootDisk(pwr_tStatus* status, char* ibuffer, int size)
{
pwr_dStatus(sts, status, SYI__NYI);
return NULL;
}
pwr_tStatus syi_UserName(char* user, int len)
{
char* p;
p = getlogin();
if (!p)
return 0;
strncpy(user, p, len);
return 1;
}
const char* syi_Hardware()
{
#if defined HW_X86_64
static const char hw[] = "x86_64";
#elif defined HW_ARM
static const char hw[] = "ARM";
#else
static const char hw[] = "x86";
#endif
return hw;
}
const char* syi_OpSys()
{
#if defined OS_LINUX
static const char opsys[] = "Linux";
#elif defined OS_MACOS
static const char opsys[] = "MacOS";
#else
static const char opsys[] = "Unknown";
#endif
return opsys;
}
char* syi_ProcessId()
{
static char pidstr[40];
sprintf(pidstr, "%u", getpid());
return pidstr;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* co_time_os.c -- OS specific time routines.
*/
#ifndef OS_LINUX
#error This file is only for Linux
#endif
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include "co_time.h"
#include "co_time_msg.h"
/* Modified to keep uptime tics as a 64-bit unsigned.
* This way uptime tics won't wrap around for another 8000 years or so
* when HZ is at a 1000.
* RK 031112
*/
pwr_tDeltaTime* time_Uptime(
pwr_tStatus* status, pwr_tDeltaTime* tp, pwr_tDeltaTime* ap)
{
pwr_tDeltaTime time;
unsigned long tics;
static pwr_tUInt64 tics_64;
struct tms buff;
static int tics_per_sec = 0;
static pwr_tTime boot_time = { 0, 0 };
static pwr_tDeltaTime max_diff = { 0, 20000000 };
pwr_tDeltaTime uptime_tics;
pwr_tTime current_time;
pwr_tDeltaTime diff;
static pwr_tUInt16 msb_flips = 0;
static pwr_tBoolean old_high_bit = 0;
pwr_tBoolean high_bit;
lldiv_t uptime_s;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
if (tp == NULL)
tp = &time;
tics = times(&buff);
high_bit = tics >> (32 - 1);
if (!high_bit && old_high_bit)
msb_flips++;
old_high_bit = high_bit;
tics_64 = ((pwr_tUInt64)msb_flips << 32) | tics;
uptime_s = lldiv(tics_64, (pwr_tInt64)tics_per_sec);
uptime_tics.tv_sec = (pwr_tInt64)uptime_s.quot;
uptime_tics.tv_nsec
= ((pwr_tUInt64)uptime_s.rem) * (1000000000 / tics_per_sec);
// pwr_Assert(tp->tv_sec >= 0 && tp->tv_nsec >= 0);
time_GetTime(&current_time);
if (!boot_time.tv_sec) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
} else {
time_Adiff(tp, &current_time, &boot_time);
time_Dsub(&diff, tp, &uptime_tics);
time_Dabs(NULL, &diff);
if (time_Dcomp(&diff, &max_diff) > 0) {
time_Asub(&boot_time, &current_time, &uptime_tics);
*tp = uptime_tics;
if (status != NULL) {
*status = TIME__CLKCHANGE;
}
}
}
if (ap != NULL)
return time_Dadd(tp, tp, ap);
else
return tp;
}
/* Return number of clock ticks since system start.
Add number of tics corresponding to delta time 'add'. */
time_tClock time_Clock(pwr_tStatus* status, pwr_tDeltaTime* ap)
{
long tics;
struct tms buff;
static int tics_per_sec = 0;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (!tics_per_sec)
tics_per_sec = sysconf(_SC_CLK_TCK);
tics = times(&buff);
if (ap != NULL) {
tics += (ap->tv_sec * tics_per_sec)
+ (ap->tv_nsec / (1000000000 / tics_per_sec));
}
return tics;
}
time_tOs* time_Os(pwr_tStatus* status, time_tOs* tp)
{
static time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
time_GetTime(tp);
return tp;
}
/* Set system time */
pwr_tStatus time_SetTime(pwr_tTime* pt)
{
pwr_tStatus sts = TIME__SUCCESS;
return sts;
}
time_tOs* time_AtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tTime* ap)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
*tp = *ap;
return tp;
}
/* Convert from Proview delta time format
to native time format. */
time_tOs* time_DtoOs(pwr_tStatus* status, time_tOs* tp, pwr_tDeltaTime* dp)
{
time_tOs os_time;
pwr_dStatus(sts, status, TIME__SUCCESS);
if (tp == NULL)
tp = &os_time;
memcpy(tp, dp, sizeof(*tp));
return tp;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef __PBDRVR__
#define __PBDRVR__
#define INIT_MODE 0x00
#define CONFIG_MODE 0x05
#define COMM_MODE 0x08
#define H_READY_MASK 0x874B2D1E
#define C_READY_MASK 0x78B4D2E1
#define IDLE 0x00
#define BUSY 0x01
#define D_DATA_IDLE 0x00
#define D_DATA_APPLY 0xF0
#define D_DATA_BUSY 0x0F
// Macros for defining ioctl commands
#define PB_IOCTL_MAGIC 'c'
#define PB_IOCTL_READCMIDESC _IO(PB_IOCTL_MAGIC, 1)
#define PB_IOCTL_READLOCALREG _IO(PB_IOCTL_MAGIC, 2)
#define PB_IOCTL_WRITECMIDESC _IO(PB_IOCTL_MAGIC, 3)
#define PB_IOCTL_HWRESET _IO(PB_IOCTL_MAGIC, 4)
#define PB_IOCTL_CMI_INIT _IO(PB_IOCTL_MAGIC, 5)
#define PB_IOCTL_READDATADESC _IO(PB_IOCTL_MAGIC, 6)
#define PB_IOCTL_CMI_WRITE _IO(PB_IOCTL_MAGIC, 7)
#define PB_IOCTL_READ_SDB _IO(PB_IOCTL_MAGIC, 8)
#define PB_IOCTL_READ_DB _IO(PB_IOCTL_MAGIC, 9)
#define PB_IOCTL_CMI_READ _IO(PB_IOCTL_MAGIC, 10)
#define PB_IOCTL_READ_IRQ_VALUES _IO(PB_IOCTL_MAGIC, 11)
#define PB_IOCTL_READ_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 12)
#define PB_IOCTL_WRITE_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 13)
#define PB_IOCTL_READVERSION _IO(PB_IOCTL_MAGIC, 14)
#define PB_IOCTL_READSERIAL _IO(PB_IOCTL_MAGIC, 15)
#define PB_IOCTL_SET_STALLTIME _IO(PB_IOCTL_MAGIC, 16)
#define ERROR_DESCR_LENGTH 32
typedef struct {
unsigned int h_ready_mask;
unsigned int h_base_address;
unsigned char h_id;
unsigned char h_int_enable;
unsigned char h_address_swap_mode;
unsigned char h_state;
unsigned int h_param_addr;
unsigned int h_data_addr;
unsigned short h_param_size;
unsigned short h_data_size;
unsigned char h_sema;
unsigned char h_ret_val;
unsigned char h_head;
unsigned char h_tail;
unsigned int h_data_descr_addr;
unsigned int c_ready_mask;
unsigned int c_base_address;
unsigned char c_id;
unsigned char c_int_enable;
unsigned char c_address_swap_mode;
unsigned char c_state;
unsigned int c_param_addr;
unsigned int c_data_addr;
unsigned short c_param_size;
unsigned short c_data_size;
unsigned char c_sema;
unsigned char c_ret_val;
unsigned char c_head;
unsigned char c_tail;
unsigned int c_data_descr_addr;
} T_CMI_DESCRIPTOR;
typedef struct {
unsigned int reg[21];
} T_LOCALREG;
typedef struct {
unsigned char d_id;
unsigned char dummy;
unsigned char d_sema_c;
unsigned char d_sema_h;
unsigned short d_data_size;
unsigned int d_data_addr;
} T_DATA_DESCR;
typedef struct {
T_PROFI_SERVICE_DESCR* sdb_ptr;
USIGN8* data_ptr;
USIGN16* data_len_ptr;
USIGN16* retval_ptr;
} cmi_request_access_struct;
typedef struct {
USIGN8 data_id; // Id of data structure
USIGN16 offset; // Offset in data area
USIGN8* data_ptr; // Pointer to data to write/to be read
USIGN16* retval_ptr; // Pointer to return value
} cmi_data_access_struct;
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef rt_futex_h
#define rt_futex_h
#ifdef __cplusplus
extern "C" {
#endif
int futex_wait(int* futex, int val);
int futex_timed_wait(int* futex, int val, const struct timespec* timespec);
int futex_wake(int* futex, int nr);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#if !defined OS_CYGWIN
#error "This file is valid only for Cygwin"
#endif
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <unistd.h>
#include "co_cdh.h"
#include "co_strtoargv.h"
#include "rt_proc.h"
#include "rt_proc_msg.h"
#include "rt_errh.h"
pwr_tStatus proc_Load(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_Start(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
char** argv;
p->pid = fork();
if (p->pid) {
if (p->pid == -1) {
errh_Error("Could not start %s, %m\nfile: %s", p->name, errno_GetStatus(),
p->file);
} else {
errh_Info("Started %s, prio: %d, pid: %d\nfile: %s", p->name, p->p_prio,
(int)p->pid, p->file);
}
} else {
sts = PROC__SUCCESS;
if (EVEN(sts))
errh_Warning("%s: error setprio, %m\nfile: %s", p->name, sts, p->file);
argv = co_StrToArgv(p->file, p->arg);
execvp(p->file, argv);
errh_Error(
"%s: error execvp, %m\nfile: %s", p->name, errno_GetStatus(), p->file);
exit(EXIT_FAILURE);
}
return sts;
}
pwr_tStatus proc_UnloadProgram(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_SchedWait()
{
return PROC__SUCCESS;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_sect.h */
/*-< SEMAPHORE.H >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore interface * */
/*------------------------------------------------------------------*--------*/
#ifndef rt_semaphore_h
#define rt_semaphore_h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
long semkey;
int semid;
int initialized;
} sem_t;
// Not POSIX. The caller generates the key
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value);
int posix_sem_init(sem_t* sem, int pshared, unsigned int value);
sem_t* posix_sem_open(const char* name, int oflag, ...);
int posix_sem_post(sem_t* sem);
int posix_sem_getvalue(sem_t* sem, int* sval);
int posix_sem_wait(sem_t* sem);
int posix_sem_trywait(sem_t* sem);
int posix_sem_unlink(const char* name);
int posix_sem_close(sem_t* sem);
int posix_sem_destroy(sem_t* sem);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef __PBDRVR__
#define __PBDRVR__
#define INIT_MODE 0x00
#define CONFIG_MODE 0x05
#define COMM_MODE 0x08
#define H_READY_MASK 0x874B2D1E
#define C_READY_MASK 0x78B4D2E1
#define IDLE 0x00
#define BUSY 0x01
#define D_DATA_IDLE 0x00
#define D_DATA_APPLY 0xF0
#define D_DATA_BUSY 0x0F
// Macros for defining ioctl commands
#define PB_IOCTL_MAGIC 'c'
#define PB_IOCTL_READCMIDESC _IO(PB_IOCTL_MAGIC, 1)
#define PB_IOCTL_READLOCALREG _IO(PB_IOCTL_MAGIC, 2)
#define PB_IOCTL_WRITECMIDESC _IO(PB_IOCTL_MAGIC, 3)
#define PB_IOCTL_HWRESET _IO(PB_IOCTL_MAGIC, 4)
#define PB_IOCTL_CMI_INIT _IO(PB_IOCTL_MAGIC, 5)
#define PB_IOCTL_READDATADESC _IO(PB_IOCTL_MAGIC, 6)
#define PB_IOCTL_CMI_WRITE _IO(PB_IOCTL_MAGIC, 7)
#define PB_IOCTL_READ_SDB _IO(PB_IOCTL_MAGIC, 8)
#define PB_IOCTL_READ_DB _IO(PB_IOCTL_MAGIC, 9)
#define PB_IOCTL_CMI_READ _IO(PB_IOCTL_MAGIC, 10)
#define PB_IOCTL_READ_IRQ_VALUES _IO(PB_IOCTL_MAGIC, 11)
#define PB_IOCTL_READ_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 12)
#define PB_IOCTL_WRITE_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 13)
#define PB_IOCTL_READVERSION _IO(PB_IOCTL_MAGIC, 14)
#define PB_IOCTL_READSERIAL _IO(PB_IOCTL_MAGIC, 15)
#define PB_IOCTL_SET_STALLTIME _IO(PB_IOCTL_MAGIC, 16)
#define ERROR_DESCR_LENGTH 32
typedef struct {
unsigned int h_ready_mask;
unsigned int h_base_address;
unsigned char h_id;
unsigned char h_int_enable;
unsigned char h_address_swap_mode;
unsigned char h_state;
unsigned int h_param_addr;
unsigned int h_data_addr;
unsigned short h_param_size;
unsigned short h_data_size;
unsigned char h_sema;
unsigned char h_ret_val;
unsigned char h_head;
unsigned char h_tail;
unsigned int h_data_descr_addr;
unsigned int c_ready_mask;
unsigned int c_base_address;
unsigned char c_id;
unsigned char c_int_enable;
unsigned char c_address_swap_mode;
unsigned char c_state;
unsigned int c_param_addr;
unsigned int c_data_addr;
unsigned short c_param_size;
unsigned short c_data_size;
unsigned char c_sema;
unsigned char c_ret_val;
unsigned char c_head;
unsigned char c_tail;
unsigned int c_data_descr_addr;
} T_CMI_DESCRIPTOR;
typedef struct {
unsigned int reg[21];
} T_LOCALREG;
typedef struct {
unsigned char d_id;
unsigned char dummy;
unsigned char d_sema_c;
unsigned char d_sema_h;
unsigned short d_data_size;
unsigned int d_data_addr;
} T_DATA_DESCR;
typedef struct {
T_PROFI_SERVICE_DESCR* sdb_ptr;
USIGN8* data_ptr;
USIGN16* data_len_ptr;
USIGN16* retval_ptr;
} cmi_request_access_struct;
typedef struct {
USIGN8 data_id; // Id of data structure
USIGN16 offset; // Offset in data area
USIGN8* data_ptr; // Pointer to data to write/to be read
USIGN16* retval_ptr; // Pointer to return value
} cmi_data_access_struct;
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_errl.c -- Logging module
Handles logging for Linux.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "rt_errh.h"
#define MAX_NO_MSG 100;
#define DEF_MAX_NO_MSG 10;
static pthread_mutex_t fileMutex;
static pthread_mutex_t termMutex;
static int mqid = -1;
static int logFile = -1;
static int newLogFile = 1;
static int term = -1;
static pthread_t tid = 0;
static int yday = -1;
static pwr_tBoolean logToStdout = FALSE;
static void (*errl_log_cb)(void*, char*, char, pwr_tStatus, int, int) = 0;
static void* errl_log_userdata = 0;
static void CheckTimeStamp(int force);
static void* log_thread(void* arg);
void errl_Init(const char* termName,
void (*log_cb)(void*, char*, char, pwr_tStatus, int, int), void* userdata)
{
pthread_mutexattr_t mutexattr;
pthread_attr_t pthreadattr;
char name[64];
char* busid = getenv(pwr_dEnvBusId);
static int initDone = 0;
int policy;
struct sched_param param;
key_t key;
int fd;
int flags = O_RDWR | O_CREAT;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
errl_log_cb = log_cb;
errl_log_userdata = userdata;
if (initDone)
return;
if ((pthread_getschedparam(pthread_self(), &policy, &param)) == -1) {
perror("rt_errl: pthread_getprio(pthread_self() ");
return;
}
pthread_mutexattr_init(&mutexattr);
if (pthread_mutex_init(&fileMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&fileMutex, mutexattr) ");
return;
}
if (pthread_mutex_init(&termMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&termMutex, mutexattr) ");
return;
}
pthread_mutexattr_destroy(&mutexattr);
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
fd = open(name, flags, mode);
if (fd == -1) {
printf("Message Queue, open failed on %s, errno: %d\n", name, errno);
}
key = ftok(name, 'm');
close(fd);
mqid = msgget(key, IPC_CREAT | 0660);
if (mqid == -1) {
perror("Open message queue: msgget ");
return;
}
pthread_attr_init(&pthreadattr);
if (pthread_create(&tid, &pthreadattr, log_thread, NULL) == -1) {
perror("rt_logmod: pthread_create ");
pthread_attr_destroy(&pthreadattr);
return;
}
pthread_attr_destroy(&pthreadattr);
param.sched_priority -= 1;
pthread_setschedparam(tid, policy, &param);
if (termName && *termName)
errl_SetTerm(termName);
logToStdout = getenv("PWR_LOG_TO_STDOUT") != NULL ? TRUE : FALSE;
initDone = 1;
return;
}
void errl_Unlink()
{
pthread_cancel(tid);
/* Remove the message queue */
msgctl(mqid, IPC_RMID, 0);
}
void errl_SetFile(const char* logFileName)
{
pwr_tStatus sts = 1;
int oflags = O_CREAT | O_APPEND | O_WRONLY;
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
close(logFile);
logFile = -1;
}
if ((logFile = open(logFileName, oflags, mode)) == -1) {
errh_Error("Cannot open log file: %s", logFileName);
sts = 2;
} else {
// errh_Info("Logging to %s", logFileName);
newLogFile = 1;
}
pthread_mutex_unlock(&fileMutex);
}
void errl_SetTerm(const char* termName)
{
int oflags = O_APPEND | O_WRONLY;
pthread_mutex_lock(&termMutex);
if (term != -1) {
close(term);
term = -1;
}
if (termName && *termName) {
if ((term = open(termName, oflags)) == -1) {
errh_Error("Cannot open terminal: %s", termName);
}
}
pthread_mutex_unlock(&termMutex);
}
static void CheckTimeStamp(int force)
{
time_t t;
struct tm tmpTm;
t = time(NULL);
localtime_r(&t, &tmpTm);
if (force || (yday != tmpTm.tm_yday)) {
char buf[64];
#define STAMP "DATE STAMP: "
write(logFile, STAMP, strlen(STAMP));
strftime(buf, sizeof(buf), "%e-%b-%Y\n", &tmpTm);
write(logFile, buf, strlen(buf));
pthread_mutex_lock(&termMutex);
if (term != -1)
write(term, buf, strlen(buf));
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s", (int)strlen(buf), buf);
yday = tmpTm.tm_yday;
}
}
static void* log_thread(void* arg)
{
int len;
errh_sMsg buf;
while (1) {
len = msgrcv(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, 0, 0);
if (len == -1) {
if (errno != EINTR) {
perror("rt_logmod.c: mq_receive ");
sleep(1);
}
} else {
switch (buf.message_type) {
case errh_eMsgType_Log:
len -= (sizeof(buf) - sizeof(buf.str) - sizeof(buf.message_type) + 1);
buf.str[len] = 0;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
/* Set up a timer if you want better performance, ML */
CheckTimeStamp(newLogFile);
newLogFile = 0;
write(logFile, buf.str, len);
write(logFile, "\n", 1);
}
pthread_mutex_unlock(&fileMutex);
pthread_mutex_lock(&termMutex);
if (term != -1) {
write(term, buf.str, len);
write(term, "\n", 1);
}
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s\n", len, buf.str);
if (errl_log_cb)
(errl_log_cb)(errl_log_userdata, buf.str, buf.severity, buf.sts,
buf.anix, buf.message_type);
break;
case errh_eMsgType_Status:
if (errl_log_cb)
(errl_log_cb)(
errl_log_userdata, 0, 0, buf.sts, buf.anix, buf.message_type);
}
}
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_inet.c -- Internet help functions */
#include "rt_inet.h"
pwr_tBoolean inet_SetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_DeleteArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_GetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#if !defined(OS_LYNX) && !defined(OS_LINUX) && !defined(OS_MACOS) \
&& !defined OS_FREEBSD
#error \
"This file is valid only for OS_LYNX and OS_LINUX and OS_MACOS and OS_FREEBSD"
#endif
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <unistd.h>
#include "co_cdh.h"
#include "co_strtoargv.h"
#include "rt_proc.h"
#include "rt_proc_msg.h"
#include "rt_errh.h"
pwr_tStatus proc_Load(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_Start(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
char** argv;
p->pid = fork();
if (p->pid) {
if (p->pid == -1) {
errh_Error("Could not start %s, %m\nfile: %s", p->name, errno_GetStatus(),
p->file);
} else {
errh_Info("Started %s, prio: %d, pid: %d\nfile: %s", p->name, p->p_prio,
(int)p->pid, p->file);
}
} else {
sts = PROC__SUCCESS;
if (EVEN(sts))
errh_Warning("%s: error setprio, %m\nfile: %s", p->name, sts, p->file);
argv = co_StrToArgv(p->file, p->arg);
execvp(p->file, argv);
errh_Error(
"%s: error execvp, %m\nfile: %s", p->name, errno_GetStatus(), p->file);
exit(EXIT_FAILURE);
}
return sts;
}
pwr_tStatus proc_UnloadProgram(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_SchedWait()
{
return PROC__SUCCESS;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_qos.c -- Queue Communication
Contains functions that are heavily os-dependant. */
#if !defined(OS_FREEBSD)
#error "This file is valid only for FreeBSD"
#endif
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "rt_hash_msg.h"
#include "rt_errh.h"
#include "rt_qdb.h"
#include "rt_futex.h"
pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
struct timespec ts;
int remaining_time = tmo;
int delta = 100;
ts.tv_sec = 0;
qdb_AssumeLocked;
qp->lock.waiting = TRUE;
qdb_Unlock;
if (tmo == -1) {
ts.tv_nsec = delta * 1000000;
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
nanosleep(&ts, 0);
}
} else {
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
if (!remaining_time) {
/* Timeout */
*status = QCOM__TMO;
qdb_Lock;
return 0;
}
if (remaining_time <= delta) {
ts.tv_nsec = remaining_time * 1000000;
remaining_time = 0;
} else {
ts.tv_nsec = delta * 1000000;
remaining_time -= delta;
}
nanosleep(&ts, 0);
}
}
return 0;
}
pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp)
{
pwr_dStatus(sts, status, QCOM__SUCCESS);
qp->lock.waiting = FALSE;
return TRUE;
}
qdb_sQlock* qos_CreateQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
return &qp->lock;
}
void qos_DeleteQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* Distribution terms
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the Software), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*-< SEMAPHORE.C >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore implementation * */
/*------------------------------------------------------------------*--------*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "rt_semaphore.h"
sem_t* posix_sem_open(const char* name, int oflag, ...)
{
key_t key = IPC_PRIVATE;
int semid, mode = 0;
struct sembuf sops[2];
sem_t* s;
if (name != NULL) {
int fd = open(name, O_WRONLY | O_CREAT, 0777);
if (fd < 0) {
return (sem_t*)-1;
}
close(fd);
key = ftok(name, 'P');
if (key < 0) {
return (sem_t*)-1;
}
}
if (oflag & O_CREAT) {
int init_value;
va_list ap;
va_start(ap, oflag);
mode = va_arg(ap, int);
init_value = va_arg(ap, unsigned int);
if (init_value < 0) {
errno = EINVAL;
return (sem_t*)-1;
}
va_end(ap);
sops[0].sem_num = 1;
sops[0].sem_op = 1; /* mark sempahore as initialuzed */
sops[0].sem_flg = 0;
sops[1].sem_num = 0;
sops[1].sem_op = init_value;
sops[1].sem_flg = 0;
mode |= IPC_CREAT;
} else {
sops[0].sem_num = 1;
sops[0].sem_op = -1; /* wait until semaphore is initialized */
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = 1; /* restore initialized flag */
sops[1].sem_flg = 0;
}
if (oflag & O_EXCL) {
mode |= IPC_EXCL;
}
semid = semget(key, 2, mode);
if (semid < 0) {
return (sem_t*)-1;
}
if (semop(semid, sops, 2) != 0) {
return (sem_t*)-1;
}
s = (sem_t*)malloc(sizeof(sem_t));
s->semid = semid;
s->initialized = 1;
s->semkey = key;
return s;
}
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value)
{
int semid;
sem->semkey = key;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | IPC_EXCL | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1;
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_init(sem_t* sem, int pshared, unsigned int value)
{
int semid;
sem->semkey = pshared ? (long)sem : IPC_PRIVATE;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1; // Initialize, so we don't need the hash table. ML
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_post(sem_t* sem)
{
static struct sembuf sops[] = { { 0, 1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_getvalue(sem_t* sem, int* sval)
{
int result;
if (sval == NULL) {
errno = EINVAL;
return -1;
}
result = semctl(sem->semid, 0, GETVAL, (union semun)0);
if (result == -1) {
return -1;
}
*sval = result;
return 0;
}
int posix_sem_wait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_trywait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO | IPC_NOWAIT } };
return semop(sem->semid, sops, 1);
}
int posix_sem_unlink(const char* name)
{
int key, semid;
key = ftok(name, 'P');
if (key < 0) {
return -1;
}
semid = semget(key, 1, 0);
if (semid < 0) {
return -1;
}
unlink(name);
return semctl(semid, 0, IPC_RMID, (union semun)0);
}
int posix_sem_close(sem_t* sem)
{
free(sem);
return 0;
}
int posix_sem_destroy(sem_t* sem)
{
return semctl(sem->semid, 0, IPC_RMID, (union semun)0);
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_sect.h */
/*-< SEMAPHORE.H >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore interface * */
/*------------------------------------------------------------------*--------*/
#ifndef rt_semaphore_h
#define rt_semaphore_h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
long semkey;
int semid;
int initialized;
} sem_t;
// Not POSIX. The caller generates the key
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value);
int posix_sem_init(sem_t* sem, int pshared, unsigned int value);
sem_t* posix_sem_open(const char* name, int oflag, ...);
int posix_sem_post(sem_t* sem);
int posix_sem_getvalue(sem_t* sem, int* sval);
int posix_sem_wait(sem_t* sem);
int posix_sem_trywait(sem_t* sem);
int posix_sem_unlink(const char* name);
int posix_sem_close(sem_t* sem);
int posix_sem_destroy(sem_t* sem);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef __PBDRVR__
#define __PBDRVR__
#define INIT_MODE 0x00
#define CONFIG_MODE 0x05
#define COMM_MODE 0x08
#define H_READY_MASK 0x874B2D1E
#define C_READY_MASK 0x78B4D2E1
#define IDLE 0x00
#define BUSY 0x01
#define D_DATA_IDLE 0x00
#define D_DATA_APPLY 0xF0
#define D_DATA_BUSY 0x0F
// Macros for defining ioctl commands
#define PB_IOCTL_MAGIC 'c'
#define PB_IOCTL_READCMIDESC _IO(PB_IOCTL_MAGIC, 1)
#define PB_IOCTL_READLOCALREG _IO(PB_IOCTL_MAGIC, 2)
#define PB_IOCTL_WRITECMIDESC _IO(PB_IOCTL_MAGIC, 3)
#define PB_IOCTL_HWRESET _IO(PB_IOCTL_MAGIC, 4)
#define PB_IOCTL_CMI_INIT _IO(PB_IOCTL_MAGIC, 5)
#define PB_IOCTL_READDATADESC _IO(PB_IOCTL_MAGIC, 6)
#define PB_IOCTL_CMI_WRITE _IO(PB_IOCTL_MAGIC, 7)
#define PB_IOCTL_READ_SDB _IO(PB_IOCTL_MAGIC, 8)
#define PB_IOCTL_READ_DB _IO(PB_IOCTL_MAGIC, 9)
#define PB_IOCTL_CMI_READ _IO(PB_IOCTL_MAGIC, 10)
#define PB_IOCTL_READ_IRQ_VALUES _IO(PB_IOCTL_MAGIC, 11)
#define PB_IOCTL_READ_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 12)
#define PB_IOCTL_WRITE_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 13)
#define PB_IOCTL_READVERSION _IO(PB_IOCTL_MAGIC, 14)
#define PB_IOCTL_READSERIAL _IO(PB_IOCTL_MAGIC, 15)
#define PB_IOCTL_SET_STALLTIME _IO(PB_IOCTL_MAGIC, 16)
#define ERROR_DESCR_LENGTH 32
typedef struct {
unsigned int h_ready_mask;
unsigned int h_base_address;
unsigned char h_id;
unsigned char h_int_enable;
unsigned char h_address_swap_mode;
unsigned char h_state;
unsigned int h_param_addr;
unsigned int h_data_addr;
unsigned short h_param_size;
unsigned short h_data_size;
unsigned char h_sema;
unsigned char h_ret_val;
unsigned char h_head;
unsigned char h_tail;
unsigned int h_data_descr_addr;
unsigned int c_ready_mask;
unsigned int c_base_address;
unsigned char c_id;
unsigned char c_int_enable;
unsigned char c_address_swap_mode;
unsigned char c_state;
unsigned int c_param_addr;
unsigned int c_data_addr;
unsigned short c_param_size;
unsigned short c_data_size;
unsigned char c_sema;
unsigned char c_ret_val;
unsigned char c_head;
unsigned char c_tail;
unsigned int c_data_descr_addr;
} T_CMI_DESCRIPTOR;
typedef struct {
unsigned int reg[21];
} T_LOCALREG;
typedef struct {
unsigned char d_id;
unsigned char dummy;
unsigned char d_sema_c;
unsigned char d_sema_h;
unsigned short d_data_size;
unsigned int d_data_addr;
} T_DATA_DESCR;
typedef struct {
T_PROFI_SERVICE_DESCR* sdb_ptr;
USIGN8* data_ptr;
USIGN16* data_len_ptr;
USIGN16* retval_ptr;
} cmi_request_access_struct;
typedef struct {
USIGN8 data_id; // Id of data structure
USIGN16 offset; // Offset in data area
USIGN8* data_ptr; // Pointer to data to write/to be read
USIGN16* retval_ptr; // Pointer to return value
} cmi_data_access_struct;
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_errl.c -- Logging module
Handles logging for Linux.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "rt_errh.h"
#define MAX_NO_MSG 100;
#define DEF_MAX_NO_MSG 10;
static pthread_mutex_t fileMutex;
static pthread_mutex_t termMutex;
static mqd_t mqid = (mqd_t)-1;
static int logFile = -1;
static int newLogFile = 1;
static int term = -1;
static pthread_t tid = 0;
static int yday = -1;
static pwr_tBoolean logToStdout = FALSE;
static void (*errl_log_cb)(void*, char*, char, pwr_tStatus, int, int) = 0;
static void* errl_log_userdata = 0;
static void CheckTimeStamp(int force);
static void* log_thread(void* arg);
void errl_Init(const char* termName,
void (*log_cb)(void*, char*, char, pwr_tStatus, int, int), void* userdata)
{
pthread_mutexattr_t mutexattr;
pthread_attr_t pthreadattr;
struct mq_attr mqattr;
mode_t mode;
int oflags;
char name[64];
char* busid = getenv(pwr_dEnvBusId);
static int initDone = 0;
int policy;
struct sched_param param;
errl_log_cb = log_cb;
errl_log_userdata = userdata;
if (initDone)
return;
if ((pthread_getschedparam(pthread_self(), &policy, &param)) == -1) {
perror("rt_errl: pthread_getprio(pthread_self() ");
return;
}
pthread_mutexattr_init(&mutexattr);
if (pthread_mutex_init(&fileMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&fileMutex, mutexattr) ");
return;
}
if (pthread_mutex_init(&termMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&termMutex, mutexattr) ");
return;
}
pthread_mutexattr_destroy(&mutexattr);
mqattr.mq_msgsize = LOG_MAX_MSG_SIZE; /* max mess size */
mqattr.mq_maxmsg = MAX_NO_MSG; /* max no of msg in this queue */
mqattr.mq_flags = 0; // O_NONBLOCK;
oflags = O_CREAT | O_RDWR;
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
mqid = mq_open(name, oflags, mode, &mqattr);
if (mqid == (mqd_t)-1) {
if (errno == EINVAL) {
mqattr.mq_maxmsg = DEF_MAX_NO_MSG; /* Try with smaller queue */
mqid = mq_open(name, oflags, mode, &mqattr);
if (mqid == (mqd_t)-1) {
perror("rt_logmod: mq_open ");
return;
}
} else {
perror("rt_logmod: mq_open ");
return;
}
}
pthread_attr_init(&pthreadattr);
if (pthread_create(&tid, &pthreadattr, log_thread, NULL) == -1) {
perror("rt_logmod: pthread_create ");
pthread_attr_destroy(&pthreadattr);
return;
}
pthread_attr_destroy(&pthreadattr);
param.sched_priority -= 1;
pthread_setschedparam(tid, policy, &param);
if (termName && *termName)
errl_SetTerm(termName);
logToStdout = getenv("PWR_LOG_TO_STDOUT") != NULL ? TRUE : FALSE;
initDone = 1;
return;
}
void errl_Unlink()
{
char name[64];
char* busid = getenv(pwr_dEnvBusId);
pthread_cancel(tid);
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
/* We don't care about return status */
mq_unlink(name);
}
void errl_SetFile(const char* logFileName)
{
pwr_tStatus sts = 1;
int oflags = O_CREAT | O_APPEND | O_WRONLY;
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
close(logFile);
logFile = -1;
}
if ((logFile = open(logFileName, oflags, mode)) == -1) {
errh_Error("Cannot open log file: %s", logFileName);
sts = 2;
} else {
// errh_Info("Logging to %s", logFileName);
newLogFile = 1;
}
pthread_mutex_unlock(&fileMutex);
}
void errl_SetTerm(const char* termName)
{
int oflags = O_APPEND | O_WRONLY;
pthread_mutex_lock(&termMutex);
if (term != -1) {
close(term);
term = -1;
}
if (termName && *termName) {
if ((term = open(termName, oflags)) == -1) {
errh_Error("Cannot open terminal: %s", termName);
}
}
pthread_mutex_unlock(&termMutex);
}
static void CheckTimeStamp(int force)
{
time_t t;
struct tm tmpTm;
t = time(NULL);
localtime_r(&t, &tmpTm);
if (force || (yday != tmpTm.tm_yday)) {
char buf[64];
#define STAMP "DATE STAMP: "
write(logFile, STAMP, strlen(STAMP));
strftime(buf, sizeof(buf), "%e-%b-%Y\n", &tmpTm);
write(logFile, buf, strlen(buf));
pthread_mutex_lock(&termMutex);
if (term != -1)
write(term, buf, strlen(buf));
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s", (int)strlen(buf), buf);
yday = tmpTm.tm_yday;
}
}
static void* log_thread(void* arg)
{
int len;
errh_sMsg buf;
while (1) {
len = mq_receive(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, NULL);
if (len == -1) {
if (errno != EINTR)
perror("rt_logmod.c: mq_receive ");
} else {
switch (buf.message_type) {
case errh_eMsgType_Log:
len -= (sizeof(buf) - sizeof(buf.str) - sizeof(buf.message_type) + 1);
buf.str[len] = 0;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
/* Set up a timer if you want better performance, ML */
CheckTimeStamp(newLogFile);
newLogFile = 0;
write(logFile, buf.str, len);
write(logFile, "\n", 1);
}
pthread_mutex_unlock(&fileMutex);
pthread_mutex_lock(&termMutex);
if (term != -1) {
write(term, buf.str, len);
write(term, "\n", 1);
}
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s\n", len, buf.str);
if (errl_log_cb)
(errl_log_cb)(errl_log_userdata, buf.str, buf.severity, buf.sts,
buf.anix, buf.message_type);
break;
case errh_eMsgType_Status:
if (errl_log_cb)
(errl_log_cb)(
errl_log_userdata, 0, 0, buf.sts, buf.anix, buf.message_type);
}
}
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_futex.c -- Futex operations
PROVIEW/R
Contains functions that are heavily os-dependant.
Author: Robert Karlsson 21 Apr 2004
Description:
This module provides an interface to futexes - "fast user level
locking in Linux". This is achieved through the multiplexing
system call sys_futex(). As implemented below this interface provides
a synchronization mechanism that can be used both between threads
in one process as well as between threads in different processes */
#if !defined(OS_LINUX)
#error "This file is valid only for OS_LINUX"
#endif
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#define FUTEX_WAIT (0)
#define FUTEX_WAKE (1)
int futex_wait(int* futex, int val)
{
int ok;
ok = syscall(SYS_futex, futex, FUTEX_WAIT, val, NULL);
if (ok == -1) {
return errno;
} else {
return ok;
}
}
int futex_timed_wait(int* futex, int val, const struct timespec* timespec)
{
int ok;
ok = syscall(SYS_futex, futex, FUTEX_WAIT, val, timespec);
if (ok == -1) {
return errno;
} else {
return ok;
}
}
int futex_wake(int* futex, int nr)
{
int ok;
ok = syscall(SYS_futex, futex, FUTEX_WAKE, nr, NULL);
if (ok == -1) {
return errno;
} else {
return ok;
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef rt_futex_h
#define rt_futex_h
#ifdef __cplusplus
extern "C" {
#endif
int futex_wait(int* futex, int val);
int futex_timed_wait(int* futex, int val, const struct timespec* timespec);
int futex_wake(int* futex, int nr);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_inet.c -- Internet help functions */
#include "rt_inet.h"
pwr_tBoolean inet_SetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_DeleteArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_GetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#if !defined(OS_LYNX) && !defined(OS_LINUX)
#error "This file is valid only for OS_LYNX and OS_LINUX"
#endif
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <unistd.h>
#include "co_cdh.h"
#include "co_strtoargv.h"
#include "rt_proc.h"
#include "rt_proc_msg.h"
#include "rt_errh.h"
pwr_tStatus proc_Load(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_Start(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
char** argv;
p->pid = fork();
if (p->pid) {
if (p->pid == -1) {
errh_Error("Could not start %s, %m\nfile: %s", p->name, errno_GetStatus(),
p->file);
} else {
errh_Info("Started %s, prio: %d, pid: %d\nfile: %s", p->name, p->p_prio,
(int)p->pid, p->file);
}
} else {
sts = PROC__SUCCESS;
if (EVEN(sts))
errh_Warning("%s: error setprio, %m\nfile: %s", p->name, sts, p->file);
argv = co_StrToArgv(p->file, p->arg);
execvp(p->file, argv);
errh_Error(
"%s: error execvp, %m\nfile: %s", p->name, errno_GetStatus(), p->file);
exit(EXIT_FAILURE);
}
return sts;
}
pwr_tStatus proc_UnloadProgram(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_SchedWait()
{
pid_t pid;
int count = 0;
int sched;
pid = getpid();
while (((sched = sched_getscheduler(pid)) == SCHED_OTHER) && (count < 5)) {
sleep(1);
count++;
}
if (sched == SCHED_OTHER)
return PROC__NOSCHED;
return PROC__SUCCESS;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_qos.c -- Queue Communication
Contains functions that are heavily os-dependant. */
#if !defined(OS_LINUX)
#error "This file is valid only for OS_LINUX"
#endif
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "rt_hash_msg.h"
#include "rt_errh.h"
#include "rt_qdb.h"
#include "rt_futex.h"
pwr_tBoolean qos_WaitQueOld(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
pwr_tDeltaTime dtime;
struct timespec dtime_ts;
sigset_t newset;
siginfo_t info;
int ok;
pwr_tBoolean signal = FALSE;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (tmo == qcom_cTmoNone)
return FALSE;
qp->lock.waiting = TRUE;
sigemptyset(&newset);
sigaddset(&newset, qdb_cSigMsg);
// qp->lock.pid = BUILDPID(getpid(), pthread_self());
// I think that each thread has it's own pid in Linux. ML
qp->lock.pid = getpid();
qdb_Unlock;
if (tmo != qcom_cTmoEternal) {
time_MsToD(&dtime, tmo);
dtime_ts.tv_sec = dtime.tv_sec;
dtime_ts.tv_nsec = dtime.tv_nsec;
ok = sigtimedwait(&newset, &info, &dtime_ts);
} else {
for (;;) {
ok = sigwaitinfo(&newset, &info);
if (ok == -1 && errno == EINTR)
continue;
break;
}
}
if (ok == -1 && errno != EAGAIN) {
errh_Error("waitQue (%d) %s", errno, strerror(errno));
} else if (!(ok == -1 || ok == qdb_cSigMsg)) {
errh_Error("qos waitQue signr %d", ok);
}
qdb_Lock;
if (qp->lock.waiting) {
*sts = QCOM__TMO;
qp->lock.waiting = FALSE;
} else {
signal = TRUE;
}
return signal;
}
pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
pwr_tDeltaTime dtime;
pwr_tTime atime;
struct timespec atime_ts;
int ok;
pwr_tBoolean signal = FALSE;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (tmo == qcom_cTmoNone)
return FALSE;
pthread_mutex_lock(&qp->lock.mutex);
qp->lock.waiting = TRUE;
qp->lock.pid = 0;
qdb_Unlock;
if (tmo != qcom_cTmoEternal) {
time_GetTimeMonotonic(&atime);
time_MsToD(&dtime, tmo);
time_Aadd(&atime, &atime, &dtime);
atime_ts.tv_sec = atime.tv_sec;
atime_ts.tv_nsec = atime.tv_nsec;
ok = pthread_cond_timedwait(&qp->lock.cond, &qp->lock.mutex, &atime_ts);
} else {
ok = pthread_cond_wait(&qp->lock.cond, &qp->lock.mutex);
}
pthread_mutex_unlock(&qp->lock.mutex);
qdb_Lock;
if ((qp->lock.waiting) || (ok == ETIMEDOUT)) {
*sts = QCOM__TMO;
qp->lock.waiting = FALSE;
} else {
signal = TRUE;
}
return signal;
}
pwr_tStatus qos_SignalQueOld(pwr_tStatus* status, qdb_sQue* qp)
{
union sigval value;
int ok;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (qp->lock.waiting) {
// value.sival_int = BUILDPID(getpid(), pthread_self());
value.sival_int = getpid();
qp->lock.waiting = FALSE;
ok = sigqueue(qp->lock.pid, qdb_cSigMsg, value);
if (ok == -1) {
*sts = errno_Status(errno);
}
}
return TRUE;
}
pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp)
{
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
pthread_mutex_lock(&qp->lock.mutex);
qp->lock.waiting = FALSE;
pthread_cond_signal(&qp->lock.cond);
pthread_mutex_unlock(&qp->lock.mutex);
return TRUE;
}
qdb_sQlock* qos_CreateQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
return &qp->lock;
}
void qos_DeleteQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* Distribution terms
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the Software), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*-< SEMAPHORE.C >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore implementation * */
/*------------------------------------------------------------------*--------*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "rt_semaphore.h"
union semun {
int val;
struct semid_ds* buf;
u_short* array;
};
sem_t* posix_sem_open(const char* name, int oflag, ...)
{
key_t key = IPC_PRIVATE;
int semid, mode = 0;
struct sembuf sops[2];
sem_t* s;
if (name != NULL) {
int fd = open(name, O_WRONLY | O_CREAT, 0777);
if (fd < 0) {
return (sem_t*)-1;
}
close(fd);
key = ftok(name, 'P');
if (key < 0) {
return (sem_t*)-1;
}
}
if (oflag & O_CREAT) {
int init_value;
va_list ap;
va_start(ap, oflag);
mode = va_arg(ap, mode_t);
init_value = va_arg(ap, unsigned int);
if (init_value < 0) {
errno = EINVAL;
return (sem_t*)-1;
}
va_end(ap);
sops[0].sem_num = 1;
sops[0].sem_op = 1; /* mark sempahore as initialuzed */
sops[0].sem_flg = 0;
sops[1].sem_num = 0;
sops[1].sem_op = init_value;
sops[1].sem_flg = 0;
mode |= IPC_CREAT;
} else {
sops[0].sem_num = 1;
sops[0].sem_op = -1; /* wait until semaphore is initialized */
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = 1; /* restore initialized flag */
sops[1].sem_flg = 0;
}
if (oflag & O_EXCL) {
mode |= IPC_EXCL;
}
semid = semget(key, 2, mode);
if (semid < 0) {
return (sem_t*)-1;
}
if (semop(semid, sops, 2) != 0) {
return (sem_t*)-1;
}
s = (sem_t*)malloc(sizeof(sem_t));
s->semid = semid;
s->initialized = 1;
s->semkey = key;
return s;
}
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value)
{
int semid;
sem->semkey = key;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | IPC_EXCL | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1;
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_init(sem_t* sem, int pshared, unsigned int value)
{
int semid;
sem->semkey = pshared ? (long)sem : IPC_PRIVATE;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1; // Initialize, so we don't need the hash table. ML
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_post(sem_t* sem)
{
static struct sembuf sops[] = { { 0, 1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_getvalue(sem_t* sem, int* sval)
{
int result;
if (sval == NULL) {
errno = EINVAL;
return -1;
}
result = semctl(sem->semid, 0, GETVAL, (union semun)0);
if (result == -1) {
return -1;
}
*sval = result;
return 0;
}
int posix_sem_wait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_trywait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO | IPC_NOWAIT } };
return semop(sem->semid, sops, 1);
}
int posix_sem_unlink(const char* name)
{
int key, semid;
key = ftok(name, 'P');
if (key < 0) {
return -1;
}
semid = semget(key, 1, 0);
if (semid < 0) {
return -1;
}
unlink(name);
return semctl(semid, 0, IPC_RMID, (union semun)0);
}
int posix_sem_close(sem_t* sem)
{
free(sem);
return 0;
}
int posix_sem_destroy(sem_t* sem)
{
return semctl(sem->semid, 0, IPC_RMID, (union semun)0);
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef __PBDRVR__
#define __PBDRVR__
#define INIT_MODE 0x00
#define CONFIG_MODE 0x05
#define COMM_MODE 0x08
#define H_READY_MASK 0x874B2D1E
#define C_READY_MASK 0x78B4D2E1
#define IDLE 0x00
#define BUSY 0x01
#define D_DATA_IDLE 0x00
#define D_DATA_APPLY 0xF0
#define D_DATA_BUSY 0x0F
// Macros for defining ioctl commands
#define PB_IOCTL_MAGIC 'c'
#define PB_IOCTL_READCMIDESC _IO(PB_IOCTL_MAGIC, 1)
#define PB_IOCTL_READLOCALREG _IO(PB_IOCTL_MAGIC, 2)
#define PB_IOCTL_WRITECMIDESC _IO(PB_IOCTL_MAGIC, 3)
#define PB_IOCTL_HWRESET _IO(PB_IOCTL_MAGIC, 4)
#define PB_IOCTL_CMI_INIT _IO(PB_IOCTL_MAGIC, 5)
#define PB_IOCTL_READDATADESC _IO(PB_IOCTL_MAGIC, 6)
#define PB_IOCTL_CMI_WRITE _IO(PB_IOCTL_MAGIC, 7)
#define PB_IOCTL_READ_SDB _IO(PB_IOCTL_MAGIC, 8)
#define PB_IOCTL_READ_DB _IO(PB_IOCTL_MAGIC, 9)
#define PB_IOCTL_CMI_READ _IO(PB_IOCTL_MAGIC, 10)
#define PB_IOCTL_READ_IRQ_VALUES _IO(PB_IOCTL_MAGIC, 11)
#define PB_IOCTL_READ_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 12)
#define PB_IOCTL_WRITE_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 13)
#define PB_IOCTL_READVERSION _IO(PB_IOCTL_MAGIC, 14)
#define PB_IOCTL_READSERIAL _IO(PB_IOCTL_MAGIC, 15)
#define PB_IOCTL_SET_STALLTIME _IO(PB_IOCTL_MAGIC, 16)
#define ERROR_DESCR_LENGTH 32
typedef struct {
unsigned int h_ready_mask;
unsigned int h_base_address;
unsigned char h_id;
unsigned char h_int_enable;
unsigned char h_address_swap_mode;
unsigned char h_state;
unsigned int h_param_addr;
unsigned int h_data_addr;
unsigned short h_param_size;
unsigned short h_data_size;
unsigned char h_sema;
unsigned char h_ret_val;
unsigned char h_head;
unsigned char h_tail;
unsigned int h_data_descr_addr;
unsigned int c_ready_mask;
unsigned int c_base_address;
unsigned char c_id;
unsigned char c_int_enable;
unsigned char c_address_swap_mode;
unsigned char c_state;
unsigned int c_param_addr;
unsigned int c_data_addr;
unsigned short c_param_size;
unsigned short c_data_size;
unsigned char c_sema;
unsigned char c_ret_val;
unsigned char c_head;
unsigned char c_tail;
unsigned int c_data_descr_addr;
} T_CMI_DESCRIPTOR;
typedef struct {
unsigned int reg[21];
} T_LOCALREG;
typedef struct {
unsigned char d_id;
unsigned char dummy;
unsigned char d_sema_c;
unsigned char d_sema_h;
unsigned short d_data_size;
unsigned int d_data_addr;
} T_DATA_DESCR;
typedef struct {
T_PROFI_SERVICE_DESCR* sdb_ptr;
USIGN8* data_ptr;
USIGN16* data_len_ptr;
USIGN16* retval_ptr;
} cmi_request_access_struct;
typedef struct {
USIGN8 data_id; // Id of data structure
USIGN16 offset; // Offset in data area
USIGN8* data_ptr; // Pointer to data to write/to be read
USIGN16* retval_ptr; // Pointer to return value
} cmi_data_access_struct;
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_errl.c -- Logging module
Handles logging for Linux.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "rt_errh.h"
#define MAX_NO_MSG 100;
#define DEF_MAX_NO_MSG 10;
static pthread_mutex_t fileMutex;
static pthread_mutex_t termMutex;
static int mqid = -1;
static int logFile = -1;
static int newLogFile = 1;
static int term = -1;
static pthread_t tid = 0;
static int yday = -1;
static pwr_tBoolean logToStdout = FALSE;
static void (*errl_log_cb)(void*, char*, char, pwr_tStatus, int, int) = 0;
static void* errl_log_userdata = 0;
static void CheckTimeStamp(int force);
static void* log_thread(void* arg);
void errl_Init(const char* termName,
void (*log_cb)(void*, char*, char, pwr_tStatus, int, int), void* userdata)
{
pthread_mutexattr_t mutexattr;
pthread_attr_t pthreadattr;
char name[64];
char* busid = getenv(pwr_dEnvBusId);
static int initDone = 0;
int policy;
struct sched_param param;
key_t key;
int fd;
int flags = O_RDWR | O_CREAT;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
errl_log_cb = log_cb;
errl_log_userdata = userdata;
if (initDone)
return;
if ((pthread_getschedparam(pthread_self(), &policy, &param)) == -1) {
perror("rt_errl: pthread_getprio(pthread_self() ");
return;
}
pthread_mutexattr_init(&mutexattr);
if (pthread_mutex_init(&fileMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&fileMutex, mutexattr) ");
return;
}
if (pthread_mutex_init(&termMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&termMutex, mutexattr) ");
return;
}
pthread_mutexattr_destroy(&mutexattr);
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
fd = open(name, flags, mode);
if (fd == -1) {
printf("Message Queue, open failed on %s, errno: %d\n", name, errno);
}
key = ftok(name, 'm');
close(fd);
mqid = msgget(key, IPC_CREAT | 0660);
if (mqid == -1) {
perror("Open message queue: msgget ");
return;
}
pthread_attr_init(&pthreadattr);
if (pthread_create(&tid, &pthreadattr, log_thread, NULL) == -1) {
perror("rt_logmod: pthread_create ");
pthread_attr_destroy(&pthreadattr);
return;
}
pthread_attr_destroy(&pthreadattr);
param.sched_priority -= 1;
pthread_setschedparam(tid, policy, &param);
if (termName && *termName)
errl_SetTerm(termName);
logToStdout = getenv("PWR_LOG_TO_STDOUT") != NULL ? TRUE : FALSE;
initDone = 1;
return;
}
void errl_Unlink()
{
pthread_cancel(tid);
/* Remove the message queue */
msgctl(mqid, IPC_RMID, 0);
}
void errl_SetFile(const char* logFileName)
{
pwr_tStatus sts = 1;
int oflags = O_CREAT | O_APPEND | O_WRONLY;
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
close(logFile);
logFile = -1;
}
if ((logFile = open(logFileName, oflags, mode)) == -1) {
errh_Error("Cannot open log file: %s", logFileName);
sts = 2;
} else {
// errh_Info("Logging to %s", logFileName);
newLogFile = 1;
}
pthread_mutex_unlock(&fileMutex);
}
void errl_SetTerm(const char* termName)
{
int oflags = O_APPEND | O_WRONLY;
pthread_mutex_lock(&termMutex);
if (term != -1) {
close(term);
term = -1;
}
if (termName && *termName) {
if ((term = open(termName, oflags)) == -1) {
errh_Error("Cannot open terminal: %s", termName);
}
}
pthread_mutex_unlock(&termMutex);
}
static void CheckTimeStamp(int force)
{
time_t t;
struct tm tmpTm;
t = time(NULL);
localtime_r(&t, &tmpTm);
if (force || (yday != tmpTm.tm_yday)) {
char buf[64];
#define STAMP "DATE STAMP: "
write(logFile, STAMP, strlen(STAMP));
strftime(buf, sizeof(buf), "%e-%b-%Y\n", &tmpTm);
write(logFile, buf, strlen(buf));
pthread_mutex_lock(&termMutex);
if (term != -1)
write(term, buf, strlen(buf));
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s", (int)strlen(buf), buf);
yday = tmpTm.tm_yday;
}
}
static void* log_thread(void* arg)
{
int len;
errh_sMsg buf;
while (1) {
len = msgrcv(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, 0, 0);
if (len == -1) {
if (errno != EINTR) {
perror("rt_logmod.c: mq_receive ");
sleep(1);
}
} else {
switch (buf.message_type) {
case errh_eMsgType_Log:
len -= (sizeof(buf) - sizeof(buf.str) - sizeof(buf.message_type) + 1);
buf.str[len] = 0;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
/* Set up a timer if you want better performance, ML */
CheckTimeStamp(newLogFile);
newLogFile = 0;
write(logFile, buf.str, len);
write(logFile, "\n", 1);
}
pthread_mutex_unlock(&fileMutex);
pthread_mutex_lock(&termMutex);
if (term != -1) {
write(term, buf.str, len);
write(term, "\n", 1);
}
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s\n", len, buf.str);
if (errl_log_cb)
(errl_log_cb)(errl_log_userdata, buf.str, buf.severity, buf.sts,
buf.anix, buf.message_type);
break;
case errh_eMsgType_Status:
if (errl_log_cb)
(errl_log_cb)(
errl_log_userdata, 0, 0, buf.sts, buf.anix, buf.message_type);
}
}
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_inet.c -- Internet help functions */
#include "rt_inet.h"
pwr_tBoolean inet_SetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_DeleteArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_GetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#if !defined(OS_LYNX) && !defined(OS_LINUX) && !defined(OS_MACOS) \
&& !defined OS_FREEBSD
#error "This file is valid only for OS_LYNX, OS_LINUX, OS_MACOS and OS_FREEBSD"
#endif
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <unistd.h>
#include "co_cdh.h"
#include "co_strtoargv.h"
#include "rt_proc.h"
#include "rt_proc_msg.h"
#include "rt_errh.h"
pwr_tStatus proc_Load(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_Start(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
char** argv;
p->pid = fork();
if (p->pid) {
if (p->pid == -1) {
errh_Error("Could not start %s, %m\nfile: %s", p->name, errno_GetStatus(),
p->file);
} else {
errh_Info("Started %s, prio: %d, pid: %d\nfile: %s", p->name, p->p_prio,
(int)p->pid, p->file);
}
} else {
sts = PROC__SUCCESS;
if (EVEN(sts))
errh_Warning("%s: error setprio, %m\nfile: %s", p->name, sts, p->file);
argv = co_StrToArgv(p->file, p->arg);
execvp(p->file, argv);
errh_Error(
"%s: error execvp, %m\nfile: %s", p->name, errno_GetStatus(), p->file);
exit(EXIT_FAILURE);
}
return sts;
}
pwr_tStatus proc_UnloadProgram(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_SchedWait()
{
return PROC__SUCCESS;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_qos.c -- Queue Communication
Contains functions that are heavily os-dependant. */
#if !defined(OS_MACOS)
#error "This file is valid only for Mac OS"
#endif
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "rt_hash_msg.h"
#include "rt_errh.h"
#include "rt_qdb.h"
#include "rt_futex.h"
pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
struct timespec ts;
int remaining_time = tmo;
int delta = 100;
ts.tv_sec = 0;
qdb_AssumeLocked;
qp->lock.waiting = TRUE;
qdb_Unlock;
if (tmo == -1) {
ts.tv_nsec = delta * 1000000;
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
nanosleep(&ts, 0);
}
} else {
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
if (!remaining_time) {
/* Timeout */
*status = QCOM__TMO;
qdb_Lock;
return 0;
}
if (remaining_time <= delta) {
ts.tv_nsec = remaining_time * 1000000;
remaining_time = 0;
} else {
ts.tv_nsec = delta * 1000000;
remaining_time -= delta;
}
nanosleep(&ts, 0);
}
}
return 0;
}
pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp)
{
pwr_dStatus(sts, status, QCOM__SUCCESS);
qp->lock.waiting = FALSE;
return TRUE;
}
qdb_sQlock* qos_CreateQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
return &qp->lock;
}
void qos_DeleteQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* Distribution terms
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the Software), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*-< SEMAPHORE.C >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore implementation * */
/*------------------------------------------------------------------*--------*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "rt_semaphore.h"
sem_t* posix_sem_open(const char* name, int oflag, ...)
{
key_t key = IPC_PRIVATE;
int semid, mode = 0;
struct sembuf sops[2];
sem_t* s;
if (name != NULL) {
int fd = open(name, O_WRONLY | O_CREAT, 0777);
if (fd < 0) {
return (sem_t*)-1;
}
close(fd);
key = ftok(name, 'P');
if (key < 0) {
return (sem_t*)-1;
}
}
if (oflag & O_CREAT) {
int init_value;
va_list ap;
va_start(ap, oflag);
mode = va_arg(ap, int);
init_value = va_arg(ap, unsigned int);
if (init_value < 0) {
errno = EINVAL;
return (sem_t*)-1;
}
va_end(ap);
sops[0].sem_num = 1;
sops[0].sem_op = 1; /* mark sempahore as initialuzed */
sops[0].sem_flg = 0;
sops[1].sem_num = 0;
sops[1].sem_op = init_value;
sops[1].sem_flg = 0;
mode |= IPC_CREAT;
} else {
sops[0].sem_num = 1;
sops[0].sem_op = -1; /* wait until semaphore is initialized */
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = 1; /* restore initialized flag */
sops[1].sem_flg = 0;
}
if (oflag & O_EXCL) {
mode |= IPC_EXCL;
}
semid = semget(key, 2, mode);
if (semid < 0) {
return (sem_t*)-1;
}
if (semop(semid, sops, 2) != 0) {
return (sem_t*)-1;
}
s = (sem_t*)malloc(sizeof(sem_t));
s->semid = semid;
s->initialized = 1;
s->semkey = key;
return s;
}
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value)
{
int semid;
sem->semkey = key;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | IPC_EXCL | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1;
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_init(sem_t* sem, int pshared, unsigned int value)
{
int semid;
sem->semkey = pshared ? (long)sem : IPC_PRIVATE;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1; // Initialize, so we don't need the hash table. ML
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_post(sem_t* sem)
{
static struct sembuf sops[] = { { 0, 1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_getvalue(sem_t* sem, int* sval)
{
int result;
if (sval == NULL) {
errno = EINVAL;
return -1;
}
result = semctl(sem->semid, 0, GETVAL, (union semun)0);
if (result == -1) {
return -1;
}
*sval = result;
return 0;
}
int posix_sem_wait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_trywait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO | IPC_NOWAIT } };
return semop(sem->semid, sops, 1);
}
int posix_sem_unlink(const char* name)
{
int key, semid;
key = ftok(name, 'P');
if (key < 0) {
return -1;
}
semid = semget(key, 1, 0);
if (semid < 0) {
return -1;
}
unlink(name);
return semctl(semid, 0, IPC_RMID, (union semun)0);
}
int posix_sem_close(sem_t* sem)
{
free(sem);
return 0;
}
int posix_sem_destroy(sem_t* sem)
{
return semctl(sem->semid, 0, IPC_RMID, (union semun)0);
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_sect.h */
/*-< SEMAPHORE.H >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore interface * */
/*------------------------------------------------------------------*--------*/
#ifndef rt_semaphore_h
#define rt_semaphore_h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
long semkey;
int semid;
int initialized;
} sem_t;
// Not POSIX. The caller generates the key
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value);
int posix_sem_init(sem_t* sem, int pshared, unsigned int value);
sem_t* posix_sem_open(const char* name, int oflag, ...);
int posix_sem_post(sem_t* sem);
int posix_sem_getvalue(sem_t* sem, int* sval);
int posix_sem_wait(sem_t* sem);
int posix_sem_trywait(sem_t* sem);
int posix_sem_unlink(const char* name);
int posix_sem_close(sem_t* sem);
int posix_sem_destroy(sem_t* sem);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef __PBDRVR__
#define __PBDRVR__
#define INIT_MODE 0x00
#define CONFIG_MODE 0x05
#define COMM_MODE 0x08
#define H_READY_MASK 0x874B2D1E
#define C_READY_MASK 0x78B4D2E1
#define IDLE 0x00
#define BUSY 0x01
#define D_DATA_IDLE 0x00
#define D_DATA_APPLY 0xF0
#define D_DATA_BUSY 0x0F
// Macros for defining ioctl commands
#define PB_IOCTL_MAGIC 'c'
#define PB_IOCTL_READCMIDESC _IO(PB_IOCTL_MAGIC, 1)
#define PB_IOCTL_READLOCALREG _IO(PB_IOCTL_MAGIC, 2)
#define PB_IOCTL_WRITECMIDESC _IO(PB_IOCTL_MAGIC, 3)
#define PB_IOCTL_HWRESET _IO(PB_IOCTL_MAGIC, 4)
#define PB_IOCTL_CMI_INIT _IO(PB_IOCTL_MAGIC, 5)
#define PB_IOCTL_READDATADESC _IO(PB_IOCTL_MAGIC, 6)
#define PB_IOCTL_CMI_WRITE _IO(PB_IOCTL_MAGIC, 7)
#define PB_IOCTL_READ_SDB _IO(PB_IOCTL_MAGIC, 8)
#define PB_IOCTL_READ_DB _IO(PB_IOCTL_MAGIC, 9)
#define PB_IOCTL_CMI_READ _IO(PB_IOCTL_MAGIC, 10)
#define PB_IOCTL_READ_IRQ_VALUES _IO(PB_IOCTL_MAGIC, 11)
#define PB_IOCTL_READ_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 12)
#define PB_IOCTL_WRITE_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 13)
#define PB_IOCTL_READVERSION _IO(PB_IOCTL_MAGIC, 14)
#define PB_IOCTL_READSERIAL _IO(PB_IOCTL_MAGIC, 15)
#define PB_IOCTL_SET_STALLTIME _IO(PB_IOCTL_MAGIC, 16)
#define ERROR_DESCR_LENGTH 32
typedef struct {
unsigned int h_ready_mask;
unsigned int h_base_address;
unsigned char h_id;
unsigned char h_int_enable;
unsigned char h_address_swap_mode;
unsigned char h_state;
unsigned int h_param_addr;
unsigned int h_data_addr;
unsigned short h_param_size;
unsigned short h_data_size;
unsigned char h_sema;
unsigned char h_ret_val;
unsigned char h_head;
unsigned char h_tail;
unsigned int h_data_descr_addr;
unsigned int c_ready_mask;
unsigned int c_base_address;
unsigned char c_id;
unsigned char c_int_enable;
unsigned char c_address_swap_mode;
unsigned char c_state;
unsigned int c_param_addr;
unsigned int c_data_addr;
unsigned short c_param_size;
unsigned short c_data_size;
unsigned char c_sema;
unsigned char c_ret_val;
unsigned char c_head;
unsigned char c_tail;
unsigned int c_data_descr_addr;
} T_CMI_DESCRIPTOR;
typedef struct {
unsigned int reg[21];
} T_LOCALREG;
typedef struct {
unsigned char d_id;
unsigned char dummy;
unsigned char d_sema_c;
unsigned char d_sema_h;
unsigned short d_data_size;
unsigned int d_data_addr;
} T_DATA_DESCR;
typedef struct {
T_PROFI_SERVICE_DESCR* sdb_ptr;
USIGN8* data_ptr;
USIGN16* data_len_ptr;
USIGN16* retval_ptr;
} cmi_request_access_struct;
typedef struct {
USIGN8 data_id; // Id of data structure
USIGN16 offset; // Offset in data area
USIGN8* data_ptr; // Pointer to data to write/to be read
USIGN16* retval_ptr; // Pointer to return value
} cmi_data_access_struct;
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_errl.c -- Logging module
Handles logging for Linux.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "rt_errh.h"
#define MAX_NO_MSG 100;
#define DEF_MAX_NO_MSG 10;
static pthread_mutex_t fileMutex;
static pthread_mutex_t termMutex;
static int mqid = -1;
static int logFile = -1;
static int newLogFile = 1;
static int term = -1;
static pthread_t tid = 0;
static int yday = -1;
static pwr_tBoolean logToStdout = FALSE;
static void (*errl_log_cb)(void*, char*, char, pwr_tStatus, int, int) = 0;
static void* errl_log_userdata = 0;
static void CheckTimeStamp(int force);
static void* log_thread(void* arg);
void errl_Init(const char* termName,
void (*log_cb)(void*, char*, char, pwr_tStatus, int, int), void* userdata)
{
pthread_mutexattr_t mutexattr;
pthread_attr_t pthreadattr;
char name[64];
char* busid = getenv(pwr_dEnvBusId);
static int initDone = 0;
int policy;
struct sched_param param;
key_t key;
int fd;
int flags = O_RDWR | O_CREAT;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
errl_log_cb = log_cb;
errl_log_userdata = userdata;
if (initDone)
return;
if ((pthread_getschedparam(pthread_self(), &policy, &param)) == -1) {
perror("rt_errl: pthread_getprio(pthread_self() ");
return;
}
pthread_mutexattr_init(&mutexattr);
if (pthread_mutex_init(&fileMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&fileMutex, mutexattr) ");
return;
}
if (pthread_mutex_init(&termMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&termMutex, mutexattr) ");
return;
}
pthread_mutexattr_destroy(&mutexattr);
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
fd = open(name, flags, mode);
if (fd == -1) {
printf("Message Queue, open failed on %s, errno: %d\n", name, errno);
}
key = ftok(name, 'm');
close(fd);
mqid = msgget(key, IPC_CREAT | 0660);
if (mqid == -1) {
perror("Open message queue: msgget ");
return;
}
pthread_attr_init(&pthreadattr);
if (pthread_create(&tid, /* &pthreadattr*/ NULL, log_thread, NULL) == -1) {
perror("rt_logmod: pthread_create ");
pthread_attr_destroy(&pthreadattr);
return;
}
pthread_attr_destroy(&pthreadattr);
param.sched_priority -= 1;
pthread_setschedparam(tid, policy, &param);
if (termName && *termName)
errl_SetTerm(termName);
logToStdout = getenv("PWR_LOG_TO_STDOUT") != NULL ? TRUE : FALSE;
initDone = 1;
return;
}
void errl_Unlink()
{
pthread_cancel(tid);
/* Remove the message queue */
msgctl(mqid, IPC_RMID, 0);
}
void errl_SetFile(const char* logFileName)
{
pwr_tStatus sts = 1;
int oflags = O_CREAT | O_APPEND | O_WRONLY;
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
close(logFile);
logFile = -1;
}
if ((logFile = open(logFileName, oflags, mode)) == -1) {
errh_Error("Cannot open log file: %s", logFileName);
sts = 2;
} else {
// errh_Info("Logging to %s", logFileName);
newLogFile = 1;
}
pthread_mutex_unlock(&fileMutex);
}
void errl_SetTerm(const char* termName)
{
int oflags = O_APPEND | O_WRONLY;
pthread_mutex_lock(&termMutex);
if (term != -1) {
close(term);
term = -1;
}
if (termName && *termName) {
if ((term = open(termName, oflags)) == -1) {
errh_Error("Cannot open terminal: %s", termName);
}
}
pthread_mutex_unlock(&termMutex);
}
static void CheckTimeStamp(int force)
{
time_t t;
struct tm tmpTm;
t = time(NULL);
localtime_r(&t, &tmpTm);
if (force || (yday != tmpTm.tm_yday)) {
char buf[64];
#define STAMP "DATE STAMP: "
write(logFile, STAMP, strlen(STAMP));
strftime(buf, sizeof(buf), "%e-%b-%Y\n", &tmpTm);
write(logFile, buf, strlen(buf));
pthread_mutex_lock(&termMutex);
if (term != -1)
write(term, buf, strlen(buf));
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s", (int)strlen(buf), buf);
yday = tmpTm.tm_yday;
}
}
static void* log_thread(void* arg)
{
int len;
errh_sMsg buf;
sleep(1);
while (1) {
len = msgrcv(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, 0, 0);
if (len == -1) {
if (errno != EINTR) {
perror("rt_logmod.c: mq_receive ");
sleep(1);
}
} else {
switch (buf.message_type) {
case errh_eMsgType_Log:
len -= (sizeof(buf) - sizeof(buf.str) - sizeof(buf.message_type) + 1);
buf.str[len] = 0;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
/* Set up a timer if you want better performance, ML */
CheckTimeStamp(newLogFile);
newLogFile = 0;
write(logFile, buf.str, len);
write(logFile, "\n", 1);
}
pthread_mutex_unlock(&fileMutex);
pthread_mutex_lock(&termMutex);
if (term != -1) {
write(term, buf.str, len);
write(term, "\n", 1);
}
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s\n", len, buf.str);
if (errl_log_cb)
(errl_log_cb)(errl_log_userdata, buf.str, buf.severity, buf.sts,
buf.anix, buf.message_type);
break;
case errh_eMsgType_Status:
if (errl_log_cb)
(errl_log_cb)(
errl_log_userdata, 0, 0, buf.sts, buf.anix, buf.message_type);
}
}
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_inet.c -- Internet help functions */
#include "rt_inet.h"
pwr_tBoolean inet_SetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_DeleteArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_GetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#if !defined(OS_LYNX) && !defined(OS_LINUX) && !defined(OS_MACOS) \
&& !defined OS_FREEBSD && !defined OS_OPENBSD
#error \
"This file is valid only for OS_LYNX and OS_LINUX and OS_MACOS and OS_FREEBSD and OS_OPENBSD"
#endif
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <unistd.h>
#include "co_cdh.h"
#include "co_strtoargv.h"
#include "rt_proc.h"
#include "rt_proc_msg.h"
#include "rt_errh.h"
pwr_tStatus proc_Load(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_Start(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
char** argv;
p->pid = fork();
if (p->pid) {
if (p->pid == -1) {
errh_Error("Could not start %s, %m\nfile: %s", p->name, errno_GetStatus(),
p->file);
} else {
errh_Info("Started %s, prio: %d, pid: %d\nfile: %s", p->name, p->p_prio,
(int)p->pid, p->file);
}
} else {
sts = PROC__SUCCESS;
if (EVEN(sts))
errh_Warning("%s: error setprio, %m\nfile: %s", p->name, sts, p->file);
argv = co_StrToArgv(p->file, p->arg);
execvp(p->file, argv);
errh_Error(
"%s: error execvp, %m\nfile: %s", p->name, errno_GetStatus(), p->file);
exit(EXIT_FAILURE);
}
return sts;
}
pwr_tStatus proc_UnloadProgram(proc_sProcess* p)
{
pwr_tStatus sts = PROC__SUCCESS;
return sts;
}
pwr_tStatus proc_SchedWait()
{
return PROC__SUCCESS;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_qos.c -- Queue Communication
Contains functions that are heavily os-dependant. */
#if !defined(OS_OPENBSD)
#error "This file is valid only for OpenBSD"
#endif
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "rt_hash_msg.h"
#include "rt_errh.h"
#include "rt_qdb.h"
#include "rt_futex.h"
pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
struct timespec ts;
int remaining_time = tmo;
int delta = 100;
ts.tv_sec = 0;
qdb_AssumeLocked;
qp->lock.waiting = TRUE;
qdb_Unlock;
if (tmo == -1) {
ts.tv_nsec = delta * 1000000;
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
nanosleep(&ts, 0);
}
} else {
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
if (!remaining_time) {
/* Timeout */
*status = QCOM__TMO;
qdb_Lock;
return 0;
}
if (remaining_time <= delta) {
ts.tv_nsec = remaining_time * 1000000;
remaining_time = 0;
} else {
ts.tv_nsec = delta * 1000000;
remaining_time -= delta;
}
nanosleep(&ts, 0);
}
}
return 0;
}
pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp)
{
pwr_dStatus(sts, status, QCOM__SUCCESS);
qp->lock.waiting = FALSE;
return TRUE;
}
qdb_sQlock* qos_CreateQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
return &qp->lock;
}
void qos_DeleteQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* Distribution terms
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the Software), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*-< SEMAPHORE.C >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore implementation * */
/*------------------------------------------------------------------*--------*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "rt_semaphore.h"
sem_t* posix_sem_open(const char* name, int oflag, ...)
{
key_t key = IPC_PRIVATE;
int semid, mode = 0;
struct sembuf sops[2];
sem_t* s;
if (name != NULL) {
int fd = open(name, O_WRONLY | O_CREAT, 0777);
if (fd < 0) {
return (sem_t*)-1;
}
close(fd);
key = ftok(name, 'P');
if (key < 0) {
return (sem_t*)-1;
}
}
if (oflag & O_CREAT) {
int init_value;
va_list ap;
va_start(ap, oflag);
mode = va_arg(ap, int);
init_value = va_arg(ap, unsigned int);
if (init_value < 0) {
errno = EINVAL;
return (sem_t*)-1;
}
va_end(ap);
sops[0].sem_num = 1;
sops[0].sem_op = 1; /* mark sempahore as initialuzed */
sops[0].sem_flg = 0;
sops[1].sem_num = 0;
sops[1].sem_op = init_value;
sops[1].sem_flg = 0;
mode |= IPC_CREAT;
} else {
sops[0].sem_num = 1;
sops[0].sem_op = -1; /* wait until semaphore is initialized */
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = 1; /* restore initialized flag */
sops[1].sem_flg = 0;
}
if (oflag & O_EXCL) {
mode |= IPC_EXCL;
}
semid = semget(key, 2, mode);
if (semid < 0) {
return (sem_t*)-1;
}
if (semop(semid, sops, 2) != 0) {
return (sem_t*)-1;
}
s = (sem_t*)malloc(sizeof(sem_t));
s->semid = semid;
s->initialized = 1;
s->semkey = key;
return s;
}
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value)
{
int semid;
sem->semkey = key;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | IPC_EXCL | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1;
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_init(sem_t* sem, int pshared, unsigned int value)
{
int semid;
sem->semkey = pshared ? (long)sem : IPC_PRIVATE;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1; // Initialize, so we don't need the hash table. ML
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_post(sem_t* sem)
{
static struct sembuf sops[] = { { 0, 1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_getvalue(sem_t* sem, int* sval)
{
int result;
if (sval == NULL) {
errno = EINVAL;
return -1;
}
result = semctl(sem->semid, 0, GETVAL, (union semun)0);
if (result == -1) {
return -1;
}
*sval = result;
return 0;
}
int posix_sem_wait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_trywait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO | IPC_NOWAIT } };
return semop(sem->semid, sops, 1);
}
int posix_sem_unlink(const char* name)
{
int key, semid;
key = ftok(name, 'P');
if (key < 0) {
return -1;
}
semid = semget(key, 1, 0);
if (semid < 0) {
return -1;
}
unlink(name);
return semctl(semid, 0, IPC_RMID, (union semun)0);
}
int posix_sem_close(sem_t* sem)
{
free(sem);
return 0;
}
int posix_sem_destroy(sem_t* sem)
{
return semctl(sem->semid, 0, IPC_RMID, (union semun)0);
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_sect.h */
/*-< SEMAPHORE.H >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore interface * */
/*------------------------------------------------------------------*--------*/
#ifndef rt_semaphore_h
#define rt_semaphore_h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
long semkey;
int semid;
int initialized;
} sem_t;
// Not POSIX. The caller generates the key
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value);
int posix_sem_init(sem_t* sem, int pshared, unsigned int value);
sem_t* posix_sem_open(const char* name, int oflag, ...);
int posix_sem_post(sem_t* sem);
int posix_sem_getvalue(sem_t* sem, int* sval);
int posix_sem_wait(sem_t* sem);
int posix_sem_trywait(sem_t* sem);
int posix_sem_unlink(const char* name);
int posix_sem_close(sem_t* sem);
int posix_sem_destroy(sem_t* sem);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef __PBDRVR__
#define __PBDRVR__
#define INIT_MODE 0x00
#define CONFIG_MODE 0x05
#define COMM_MODE 0x08
#define H_READY_MASK 0x874B2D1E
#define C_READY_MASK 0x78B4D2E1
#define IDLE 0x00
#define BUSY 0x01
#define D_DATA_IDLE 0x00
#define D_DATA_APPLY 0xF0
#define D_DATA_BUSY 0x0F
// Macros for defining ioctl commands
#define PB_IOCTL_MAGIC 'c'
#define PB_IOCTL_READCMIDESC _IO(PB_IOCTL_MAGIC, 1)
#define PB_IOCTL_READLOCALREG _IO(PB_IOCTL_MAGIC, 2)
#define PB_IOCTL_WRITECMIDESC _IO(PB_IOCTL_MAGIC, 3)
#define PB_IOCTL_HWRESET _IO(PB_IOCTL_MAGIC, 4)
#define PB_IOCTL_CMI_INIT _IO(PB_IOCTL_MAGIC, 5)
#define PB_IOCTL_READDATADESC _IO(PB_IOCTL_MAGIC, 6)
#define PB_IOCTL_CMI_WRITE _IO(PB_IOCTL_MAGIC, 7)
#define PB_IOCTL_READ_SDB _IO(PB_IOCTL_MAGIC, 8)
#define PB_IOCTL_READ_DB _IO(PB_IOCTL_MAGIC, 9)
#define PB_IOCTL_CMI_READ _IO(PB_IOCTL_MAGIC, 10)
#define PB_IOCTL_READ_IRQ_VALUES _IO(PB_IOCTL_MAGIC, 11)
#define PB_IOCTL_READ_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 12)
#define PB_IOCTL_WRITE_FIRST_SLAVE _IO(PB_IOCTL_MAGIC, 13)
#define PB_IOCTL_READVERSION _IO(PB_IOCTL_MAGIC, 14)
#define PB_IOCTL_READSERIAL _IO(PB_IOCTL_MAGIC, 15)
#define PB_IOCTL_SET_STALLTIME _IO(PB_IOCTL_MAGIC, 16)
#define ERROR_DESCR_LENGTH 32
typedef struct {
unsigned int h_ready_mask;
unsigned int h_base_address;
unsigned char h_id;
unsigned char h_int_enable;
unsigned char h_address_swap_mode;
unsigned char h_state;
unsigned int h_param_addr;
unsigned int h_data_addr;
unsigned short h_param_size;
unsigned short h_data_size;
unsigned char h_sema;
unsigned char h_ret_val;
unsigned char h_head;
unsigned char h_tail;
unsigned int h_data_descr_addr;
unsigned int c_ready_mask;
unsigned int c_base_address;
unsigned char c_id;
unsigned char c_int_enable;
unsigned char c_address_swap_mode;
unsigned char c_state;
unsigned int c_param_addr;
unsigned int c_data_addr;
unsigned short c_param_size;
unsigned short c_data_size;
unsigned char c_sema;
unsigned char c_ret_val;
unsigned char c_head;
unsigned char c_tail;
unsigned int c_data_descr_addr;
} T_CMI_DESCRIPTOR;
typedef struct {
unsigned int reg[21];
} T_LOCALREG;
typedef struct {
unsigned char d_id;
unsigned char dummy;
unsigned char d_sema_c;
unsigned char d_sema_h;
unsigned short d_data_size;
unsigned int d_data_addr;
} T_DATA_DESCR;
typedef struct {
T_PROFI_SERVICE_DESCR* sdb_ptr;
USIGN8* data_ptr;
USIGN16* data_len_ptr;
USIGN16* retval_ptr;
} cmi_request_access_struct;
typedef struct {
USIGN8 data_id; // Id of data structure
USIGN16 offset; // Offset in data area
USIGN8* data_ptr; // Pointer to data to write/to be read
USIGN16* retval_ptr; // Pointer to return value
} cmi_data_access_struct;
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_errl.c -- Logging module
Handles logging for Linux.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "rt_errh.h"
#define MAX_NO_MSG 100;
#define DEF_MAX_NO_MSG 10;
static pthread_mutex_t fileMutex;
static pthread_mutex_t termMutex;
static mqd_t mqid = (mqd_t)-1;
static int logFile = -1;
static int newLogFile = 1;
static int term = -1;
static pthread_t tid = 0;
static int yday = -1;
static pwr_tBoolean logToStdout = FALSE;
static void (*errl_log_cb)(void*, char*, char, pwr_tStatus, int, int) = 0;
static void* errl_log_userdata = 0;
static void CheckTimeStamp(int force);
static void* log_thread(void* arg);
void errl_Init(const char* termName,
void (*log_cb)(void*, char*, char, pwr_tStatus, int, int), void* userdata)
{
pthread_mutexattr_t mutexattr;
pthread_attr_t pthreadattr;
struct mq_attr mqattr;
mode_t mode;
int oflags;
char name[64];
char* busid = getenv(pwr_dEnvBusId);
static int initDone = 0;
int policy;
struct sched_param param;
errl_log_cb = log_cb;
errl_log_userdata = userdata;
if (initDone)
return;
if ((pthread_getschedparam(pthread_self(), &policy, &param)) == -1) {
perror("rt_errl: pthread_getprio(pthread_self() ");
return;
}
pthread_mutexattr_init(&mutexattr);
if (pthread_mutex_init(&fileMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&fileMutex, mutexattr) ");
return;
}
if (pthread_mutex_init(&termMutex, &mutexattr) == -1) {
perror("rt_logmod: pthread_mutex_init(&termMutex, mutexattr) ");
return;
}
pthread_mutexattr_destroy(&mutexattr);
mqattr.mq_msgsize = LOG_MAX_MSG_SIZE; /* max mess size */
mqattr.mq_maxmsg = MAX_NO_MSG; /* max no of msg in this queue */
mqattr.mq_flags = 0; // O_NONBLOCK;
oflags = O_CREAT | O_RDWR;
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
mqid = mq_open(name, oflags, mode, &mqattr);
if (mqid == (mqd_t)-1) {
if (errno == EINVAL) {
mqattr.mq_maxmsg = DEF_MAX_NO_MSG; /* Try with smaller queue */
mqid = mq_open(name, oflags, mode, &mqattr);
if (mqid == (mqd_t)-1) {
perror("rt_logmod: mq_open ");
return;
}
} else {
perror("rt_logmod: mq_open ");
return;
}
}
pthread_attr_init(&pthreadattr);
if (pthread_create(&tid, &pthreadattr, log_thread, NULL) == -1) {
perror("rt_logmod: pthread_create ");
pthread_attr_destroy(&pthreadattr);
return;
}
pthread_attr_destroy(&pthreadattr);
param.sched_priority -= 1;
pthread_setschedparam(tid, policy, &param);
if (termName && *termName)
errl_SetTerm(termName);
logToStdout = getenv("PWR_LOG_TO_STDOUT") != NULL ? TRUE : FALSE;
initDone = 1;
return;
}
void errl_Unlink()
{
char name[64];
char* busid = getenv(pwr_dEnvBusId);
pthread_cancel(tid);
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
/* We don't care about return status */
mq_unlink(name);
}
void errl_SetFile(const char* logFileName)
{
pwr_tStatus sts = 1;
int oflags = O_CREAT | O_APPEND | O_WRONLY;
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
close(logFile);
logFile = -1;
}
if ((logFile = open(logFileName, oflags, mode)) == -1) {
errh_Error("Cannot open log file: %s", logFileName);
sts = 2;
} else {
// errh_Info("Logging to %s", logFileName);
newLogFile = 1;
}
pthread_mutex_unlock(&fileMutex);
}
void errl_SetTerm(const char* termName)
{
int oflags = O_APPEND | O_WRONLY;
pthread_mutex_lock(&termMutex);
if (term != -1) {
close(term);
term = -1;
}
if (termName && *termName) {
if ((term = open(termName, oflags)) == -1) {
errh_Error("Cannot open terminal: %s", termName);
}
}
pthread_mutex_unlock(&termMutex);
}
static void CheckTimeStamp(int force)
{
time_t t;
struct tm tmpTm;
t = time(NULL);
localtime_r(&t, &tmpTm);
if (force || (yday != tmpTm.tm_yday)) {
char buf[64];
#define STAMP "DATE STAMP: "
write(logFile, STAMP, strlen(STAMP));
strftime(buf, sizeof(buf), "%e-%b-%Y\n", &tmpTm);
write(logFile, buf, strlen(buf));
pthread_mutex_lock(&termMutex);
if (term != -1)
write(term, buf, strlen(buf));
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s", (int)strlen(buf), buf);
yday = tmpTm.tm_yday;
}
}
static void* log_thread(void* arg)
{
int len;
errh_sMsg buf;
while (1) {
len = mq_receive(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, NULL);
if (len == -1) {
if (errno != EINTR)
perror("rt_logmod.c: mq_receive ");
} else {
switch (buf.message_type) {
case errh_eMsgType_Log:
len -= (sizeof(buf) - sizeof(buf.str) - sizeof(buf.message_type) + 1);
buf.str[len] = 0;
pthread_mutex_lock(&fileMutex);
if (logFile != -1) {
/* Set up a timer if you want better performance, ML */
CheckTimeStamp(newLogFile);
newLogFile = 0;
write(logFile, buf.str, len);
write(logFile, "\n", 1);
}
pthread_mutex_unlock(&fileMutex);
pthread_mutex_lock(&termMutex);
if (term != -1) {
write(term, buf.str, len);
write(term, "\n", 1);
}
pthread_mutex_unlock(&termMutex);
if (logToStdout)
printf("%.*s\n", len, buf.str);
if (errl_log_cb)
(errl_log_cb)(errl_log_userdata, buf.str, buf.severity, buf.sts,
buf.anix, buf.message_type);
break;
case errh_eMsgType_Status:
if (errl_log_cb)
(errl_log_cb)(
errl_log_userdata, 0, 0, buf.sts, buf.anix, buf.message_type);
}
}
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_futex.c -- Futex operations
PROVIEW/R
Contains functions that are heavily os-dependant.
Author: Robert Karlsson 21 Apr 2004
Description:
This module provides an interface to futexes - "fast user level
locking in Linux". This is achieved through the multiplexing
system call sys_futex(). As implemented below this interface provides
a synchronization mechanism that can be used both between threads
in one process as well as between threads in different processes */
#if !defined(OS_LINUX)
#error "This file is valid only for OS_LINUX"
#endif
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#define FUTEX_WAIT (0)
#define FUTEX_WAKE (1)
int futex_wait(int* futex, int val)
{
int ok;
ok = syscall(SYS_futex, futex, FUTEX_WAIT, val, NULL);
if (ok == -1) {
return errno;
} else {
return ok;
}
}
int futex_timed_wait(int* futex, int val, const struct timespec* timespec)
{
int ok;
ok = syscall(SYS_futex, futex, FUTEX_WAIT, val, timespec);
if (ok == -1) {
return errno;
} else {
return ok;
}
}
int futex_wake(int* futex, int nr)
{
int ok;
ok = syscall(SYS_futex, futex, FUTEX_WAKE, nr, NULL);
if (ok == -1) {
return errno;
} else {
return ok;
}
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
#ifndef rt_futex_h
#define rt_futex_h
#ifdef __cplusplus
extern "C" {
#endif
int futex_wait(int* futex, int val);
int futex_timed_wait(int* futex, int val, const struct timespec* timespec);
int futex_wake(int* futex, int nr);
#ifdef __cplusplus
}
#endif
#endif
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_inet.c -- Internet help functions */
#include "rt_inet.h"
pwr_tBoolean inet_SetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_DeleteArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
pwr_tBoolean inet_GetArpEntry(pwr_tStatus* sts, int s, struct arpreq* rp)
{
return 1;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_qos.c -- Queue Communication
Contains functions that are heavily os-dependant. */
#if !defined(OS_LINUX)
#error "This file is valid only for OS_LINUX"
#endif
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "co_errno.h"
#include "rt_hash_msg.h"
#include "rt_errh.h"
#include "rt_qdb.h"
#include "rt_futex.h"
pwr_tBoolean qos_WaitQueOld(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
pwr_tDeltaTime dtime;
struct timespec dtime_ts;
sigset_t newset;
siginfo_t info;
int ok;
pwr_tBoolean signal = FALSE;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (tmo == qcom_cTmoNone)
return FALSE;
qp->lock.waiting = TRUE;
sigemptyset(&newset);
sigaddset(&newset, qdb_cSigMsg);
// qp->lock.pid = BUILDPID(getpid(), pthread_self());
// I think that each thread has it's own pid in Linux. ML
qp->lock.pid = getpid();
qdb_Unlock;
if (tmo != qcom_cTmoEternal) {
time_MsToD(&dtime, tmo);
dtime_ts.tv_sec = dtime.tv_sec;
dtime_ts.tv_nsec = dtime.tv_nsec;
ok = sigtimedwait(&newset, &info, &dtime_ts);
} else {
for (;;) {
ok = sigwaitinfo(&newset, &info);
if (ok == -1 && errno == EINTR)
continue;
break;
}
}
if (ok == -1 && errno != EAGAIN) {
errh_Error("waitQue (%d) %s", errno, strerror(errno));
} else if (!(ok == -1 || ok == qdb_cSigMsg)) {
errh_Error("qos waitQue signr %d", ok);
}
qdb_Lock;
if (qp->lock.waiting) {
*sts = QCOM__TMO;
qp->lock.waiting = FALSE;
} else {
signal = TRUE;
}
return signal;
}
pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{
pwr_tDeltaTime dtime;
pwr_tTime atime;
struct timespec atime_ts;
int ok;
pwr_tBoolean signal = FALSE;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (tmo == qcom_cTmoNone)
return FALSE;
pthread_mutex_lock(&qp->lock.mutex);
qp->lock.waiting = TRUE;
qp->lock.pid = 0;
qdb_Unlock;
if (tmo != qcom_cTmoEternal) {
time_GetTime(&atime);
time_MsToD(&dtime, tmo);
time_Aadd(&atime, &atime, &dtime);
atime_ts.tv_sec = atime.tv_sec;
atime_ts.tv_nsec = atime.tv_nsec;
ok = pthread_cond_timedwait(&qp->lock.cond, &qp->lock.mutex, &atime_ts);
} else {
ok = pthread_cond_wait(&qp->lock.cond, &qp->lock.mutex);
}
pthread_mutex_unlock(&qp->lock.mutex);
qdb_Lock;
if ((qp->lock.waiting) || (ok == ETIMEDOUT)) {
*sts = QCOM__TMO;
qp->lock.waiting = FALSE;
} else {
signal = TRUE;
}
return signal;
}
pwr_tStatus qos_SignalQueOld(pwr_tStatus* status, qdb_sQue* qp)
{
union sigval value;
int ok;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (qp->lock.waiting) {
// value.sival_int = BUILDPID(getpid(), pthread_self());
value.sival_int = getpid();
qp->lock.waiting = FALSE;
ok = sigqueue(qp->lock.pid, qdb_cSigMsg, value);
if (ok == -1) {
*sts = errno_Status(errno);
}
}
return TRUE;
}
pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp)
{
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
pthread_mutex_lock(&qp->lock.mutex);
qp->lock.waiting = FALSE;
pthread_cond_signal(&qp->lock.cond);
pthread_mutex_unlock(&qp->lock.mutex);
return TRUE;
}
qdb_sQlock* qos_CreateQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
return &qp->lock;
}
void qos_DeleteQlock(pwr_tStatus* sts, qdb_sQue* qp)
{
qdb_AssumeLocked;
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* Distribution terms
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the Software), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*-< SEMAPHORE.C >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore implementation * */
/*------------------------------------------------------------------*--------*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include "rt_semaphore.h"
union semun {
int val;
struct semid_ds* buf;
u_short* array;
};
sem_t* posix_sem_open(const char* name, int oflag, ...)
{
key_t key = IPC_PRIVATE;
int semid, mode = 0;
struct sembuf sops[2];
sem_t* s;
if (name != NULL) {
int fd = open(name, O_WRONLY | O_CREAT, 0777);
if (fd < 0) {
return (sem_t*)-1;
}
close(fd);
key = ftok(name, 'P');
if (key < 0) {
return (sem_t*)-1;
}
}
if (oflag & O_CREAT) {
int init_value;
va_list ap;
va_start(ap, oflag);
mode = va_arg(ap, mode_t);
init_value = va_arg(ap, unsigned int);
if (init_value < 0) {
errno = EINVAL;
return (sem_t*)-1;
}
va_end(ap);
sops[0].sem_num = 1;
sops[0].sem_op = 1; /* mark sempahore as initialuzed */
sops[0].sem_flg = 0;
sops[1].sem_num = 0;
sops[1].sem_op = init_value;
sops[1].sem_flg = 0;
mode |= IPC_CREAT;
} else {
sops[0].sem_num = 1;
sops[0].sem_op = -1; /* wait until semaphore is initialized */
sops[0].sem_flg = 0;
sops[1].sem_num = 1;
sops[1].sem_op = 1; /* restore initialized flag */
sops[1].sem_flg = 0;
}
if (oflag & O_EXCL) {
mode |= IPC_EXCL;
}
semid = semget(key, 2, mode);
if (semid < 0) {
return (sem_t*)-1;
}
if (semop(semid, sops, 2) != 0) {
return (sem_t*)-1;
}
s = (sem_t*)malloc(sizeof(sem_t));
s->semid = semid;
s->initialized = 1;
s->semkey = key;
return s;
}
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value)
{
int semid;
sem->semkey = key;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | IPC_EXCL | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1;
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_init(sem_t* sem, int pshared, unsigned int value)
{
int semid;
sem->semkey = pshared ? (long)sem : IPC_PRIVATE;
sem->initialized = 0;
sem->semid = -1;
semid = semget(sem->semkey, 1, IPC_CREAT | 0777);
if (semid < 0) {
return -1;
}
sem->initialized = 1; // Initialize, so we don't need the hash table. ML
sem->semid = semid;
if (value != 0) {
struct sembuf sops[1];
sops[0].sem_num = 0;
sops[0].sem_op = value;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1) != 0) {
return -1;
}
}
return 0;
}
int posix_sem_post(sem_t* sem)
{
static struct sembuf sops[] = { { 0, 1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_getvalue(sem_t* sem, int* sval)
{
int result;
if (sval == NULL) {
errno = EINVAL;
return -1;
}
result = semctl(sem->semid, 0, GETVAL, (union semun)0);
if (result == -1) {
return -1;
}
*sval = result;
return 0;
}
int posix_sem_wait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO } };
return semop(sem->semid, sops, 1);
}
int posix_sem_trywait(sem_t* sem)
{
static struct sembuf sops[] = { { 0, -1, SEM_UNDO | IPC_NOWAIT } };
return semop(sem->semid, sops, 1);
}
int posix_sem_unlink(const char* name)
{
int key, semid;
key = ftok(name, 'P');
if (key < 0) {
return -1;
}
semid = semget(key, 1, 0);
if (semid < 0) {
return -1;
}
unlink(name);
return semctl(semid, 0, IPC_RMID, (union semun)0);
}
int posix_sem_close(sem_t* sem)
{
free(sem);
return 0;
}
int posix_sem_destroy(sem_t* sem)
{
return semctl(sem->semid, 0, IPC_RMID, (union semun)0);
}
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2018 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
/* rt_sect.h */
/*-< SEMAPHORE.H >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */
/* * / \ */
/* Created: 25-Aug-98 K.A. Knizhnik * / [] \ */
/* Last update: 27-Aug-98 K.A. Knizhnik * GARRET */
/*------------------------------------------------------------------*--------*/
/* Semaphore interface * */
/*------------------------------------------------------------------*--------*/
#ifndef rt_semaphore_h
#define rt_semaphore_h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
long semkey;
int semid;
int initialized;
} sem_t;
// Not POSIX. The caller generates the key
int posix_sem_init_shared(sem_t* sem, int key, unsigned int value);
int posix_sem_init(sem_t* sem, int pshared, unsigned int value);
sem_t* posix_sem_open(const char* name, int oflag, ...);
int posix_sem_post(sem_t* sem);
int posix_sem_getvalue(sem_t* sem, int* sval);
int posix_sem_wait(sem_t* sem);
int posix_sem_trywait(sem_t* sem);
int posix_sem_unlink(const char* name);
int posix_sem_close(sem_t* sem);
int posix_sem_destroy(sem_t* sem);
#ifdef __cplusplus
}
#endif
#endif
...@@ -41,7 +41,9 @@ ...@@ -41,7 +41,9 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#if !defined(OS_MACOS) && !defined(OS_OPENBSD)
#include <mqueue.h> #include <mqueue.h>
#endif
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
...@@ -54,7 +56,11 @@ ...@@ -54,7 +56,11 @@
static pthread_mutex_t fileMutex; static pthread_mutex_t fileMutex;
static pthread_mutex_t termMutex; static pthread_mutex_t termMutex;
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
static int mqid = -1;
#else
static mqd_t mqid = (mqd_t)-1; static mqd_t mqid = (mqd_t)-1;
#endif
static int logFile = -1; static int logFile = -1;
static int newLogFile = 1; static int newLogFile = 1;
static int term = -1; static int term = -1;
...@@ -72,14 +78,22 @@ void errl_Init(const char* termName, ...@@ -72,14 +78,22 @@ void errl_Init(const char* termName,
{ {
pthread_mutexattr_t mutexattr; pthread_mutexattr_t mutexattr;
pthread_attr_t pthreadattr; pthread_attr_t pthreadattr;
#if !defined(OS_MACOS) && !defined(OS_FREEBSD) && !defined(OS_OPENBSD)
struct mq_attr mqattr; struct mq_attr mqattr;
mode_t mode; mode_t mode;
int oflags; int oflags;
#endif
char name[64]; char name[64];
char* busid = getenv(pwr_dEnvBusId); char* busid = getenv(pwr_dEnvBusId);
static int initDone = 0; static int initDone = 0;
int policy; int policy;
struct sched_param param; struct sched_param param;
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
key_t key;
int fd;
int flags = O_RDWR | O_CREAT;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
#endif
errl_log_cb = log_cb; errl_log_cb = log_cb;
errl_log_userdata = userdata; errl_log_userdata = userdata;
...@@ -104,13 +118,28 @@ void errl_Init(const char* termName, ...@@ -104,13 +118,28 @@ void errl_Init(const char* termName,
} }
pthread_mutexattr_destroy(&mutexattr); pthread_mutexattr_destroy(&mutexattr);
#if !defined(OS_MACOS) && !defined(OS_FREEBSD) && !defined(OS_OPENBSD)
mqattr.mq_msgsize = LOG_MAX_MSG_SIZE; /* max mess size */ mqattr.mq_msgsize = LOG_MAX_MSG_SIZE; /* max mess size */
mqattr.mq_maxmsg = MAX_NO_MSG; /* max no of msg in this queue */ mqattr.mq_maxmsg = MAX_NO_MSG; /* max no of msg in this queue */
mqattr.mq_flags = 0; // O_NONBLOCK; mqattr.mq_flags = 0; // O_NONBLOCK;
oflags = O_CREAT | O_RDWR; oflags = O_CREAT | O_RDWR;
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
#endif
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : ""); sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
fd = open(name, flags, mode);
if (fd == -1) {
printf("Message Queue, open failed on %s, errno: %d\n", name, errno);
}
key = ftok(name, 'm');
close(fd);
mqid = msgget(key, IPC_CREAT | 0660);
if (mqid == -1) {
perror("Open message queue: msgget ");
return;
}
#else
mqid = mq_open(name, oflags, mode, &mqattr); mqid = mq_open(name, oflags, mode, &mqattr);
if (mqid == (mqd_t)-1) { if (mqid == (mqd_t)-1) {
if (errno == EINVAL) { if (errno == EINVAL) {
...@@ -125,6 +154,7 @@ void errl_Init(const char* termName, ...@@ -125,6 +154,7 @@ void errl_Init(const char* termName,
return; return;
} }
} }
#endif
pthread_attr_init(&pthreadattr); pthread_attr_init(&pthreadattr);
if (pthread_create(&tid, &pthreadattr, log_thread, NULL) == -1) { if (pthread_create(&tid, &pthreadattr, log_thread, NULL) == -1) {
...@@ -148,15 +178,21 @@ void errl_Init(const char* termName, ...@@ -148,15 +178,21 @@ void errl_Init(const char* termName,
} }
void errl_Unlink() void errl_Unlink()
{ {
#if !defined(OS_MACOS) && !defined(OS_FREEBSD) && !defined(OS_OPENBSD)
char name[64]; char name[64];
char* busid = getenv(pwr_dEnvBusId); char* busid = getenv(pwr_dEnvBusId);
#endif
pthread_cancel(tid); pthread_cancel(tid);
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
msgctl(mqid, IPC_RMID, 0);
#else
sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : ""); sprintf(name, "%s_%s", LOG_QUEUE_NAME, busid ? busid : "");
/* We don't care about return status */ /* We don't care about return status */
mq_unlink(name); mq_unlink(name);
#endif
} }
void errl_SetFile(const char* logFileName) void errl_SetFile(const char* logFileName)
{ {
...@@ -232,7 +268,11 @@ static void* log_thread(void* arg) ...@@ -232,7 +268,11 @@ static void* log_thread(void* arg)
errh_sMsg buf; errh_sMsg buf;
while (1) { while (1) {
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
len = msgrcv(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, 0, 0);
#else
len = mq_receive(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, NULL); len = mq_receive(mqid, (char*)&buf, LOG_MAX_MSG_SIZE, NULL);
#endif
if (len == -1) { if (len == -1) {
if (errno != EINTR) if (errno != EINTR)
perror("rt_logmod.c: mq_receive "); perror("rt_logmod.c: mq_receive ");
......
...@@ -34,10 +34,6 @@ ...@@ -34,10 +34,6 @@
* General Public License plus this exception. * General Public License plus this exception.
*/ */
#if !defined(OS_LYNX) && !defined(OS_LINUX)
#error "This file is valid only for OS_LYNX and OS_LINUX"
#endif
#include <errno.h> #include <errno.h>
#include <sched.h> #include <sched.h>
#include <string.h> #include <string.h>
...@@ -93,6 +89,7 @@ pwr_tStatus proc_UnloadProgram(proc_sProcess* p) ...@@ -93,6 +89,7 @@ pwr_tStatus proc_UnloadProgram(proc_sProcess* p)
pwr_tStatus proc_SchedWait() pwr_tStatus proc_SchedWait()
{ {
#if defined(OS_LINUX)
pid_t pid; pid_t pid;
int count = 0; int count = 0;
int sched; int sched;
...@@ -105,5 +102,6 @@ pwr_tStatus proc_SchedWait() ...@@ -105,5 +102,6 @@ pwr_tStatus proc_SchedWait()
} }
if (sched == SCHED_OTHER) if (sched == SCHED_OTHER)
return PROC__NOSCHED; return PROC__NOSCHED;
#endif
return PROC__SUCCESS; return PROC__SUCCESS;
} }
...@@ -38,10 +38,6 @@ ...@@ -38,10 +38,6 @@
Contains functions that are heavily os-dependant. */ Contains functions that are heavily os-dependant. */
#if !defined OS_CYGWIN
#error "This file is valid only for Cygwin"
#endif
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
...@@ -51,15 +47,62 @@ ...@@ -51,15 +47,62 @@
#include "rt_hash_msg.h" #include "rt_hash_msg.h"
#include "rt_errh.h" #include "rt_errh.h"
#include "rt_qdb.h" #include "rt_qdb.h"
#include "rt_futex.h"
pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo) pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
{ {
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
struct timespec ts;
int remaining_time = tmo;
int delta = 100;
ts.tv_sec = 0;
qdb_AssumeLocked;
qp->lock.waiting = TRUE;
qdb_Unlock;
if (tmo == -1) {
ts.tv_nsec = delta * 1000000;
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
nanosleep(&ts, 0);
}
} else {
while (1) {
if (!qp->lock.waiting) {
*status = QCOM__SUCCESS;
qdb_Lock;
return 1;
}
if (!remaining_time) {
/* Timeout */
*status = QCOM__TMO;
qdb_Lock;
return 0;
}
if (remaining_time <= delta) {
ts.tv_nsec = remaining_time * 1000000;
remaining_time = 0;
} else {
ts.tv_nsec = delta * 1000000;
remaining_time -= delta;
}
nanosleep(&ts, 0);
}
}
#else
pwr_tDeltaTime dtime; pwr_tDeltaTime dtime;
pwr_tTime atime; pwr_tTime atime;
struct timespec atime_ts; struct timespec atime_ts;
int ok; int ok;
pwr_tBoolean signal = FALSE;
pwr_dStatus(sts, status, QCOM__SUCCESS); pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked; qdb_AssumeLocked;
...@@ -75,7 +118,11 @@ pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo) ...@@ -75,7 +118,11 @@ pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
qdb_Unlock; qdb_Unlock;
if (tmo != qcom_cTmoEternal) { if (tmo != qcom_cTmoEternal) {
#if defined(OS_CYGWIN)
time_GetTime(&atime); time_GetTime(&atime);
#else
time_GetTimeMonotonic(&atime);
#endif
time_MsToD(&dtime, tmo); time_MsToD(&dtime, tmo);
time_Aadd(&atime, &atime, &dtime); time_Aadd(&atime, &atime, &dtime);
atime_ts.tv_sec = atime.tv_sec; atime_ts.tv_sec = atime.tv_sec;
...@@ -94,48 +141,29 @@ pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo) ...@@ -94,48 +141,29 @@ pwr_tBoolean qos_WaitQue(pwr_tStatus* status, qdb_sQue* qp, int tmo)
*sts = QCOM__TMO; *sts = QCOM__TMO;
qp->lock.waiting = FALSE; qp->lock.waiting = FALSE;
} else { } else {
signal = TRUE;
}
return signal;
}
pwr_tStatus qos_SignalQueOld(pwr_tStatus* status, qdb_sQue* qp)
{
union sigval value;
int ok;
pwr_dStatus(sts, status, QCOM__SUCCESS);
qdb_AssumeLocked;
if (qp->lock.waiting) {
// value.sival_int = BUILDPID(getpid(), pthread_self());
value.sival_int = getpid();
qp->lock.waiting = FALSE;
ok = sigqueue(qp->lock.pid, qdb_cSigMsg, value);
if (ok == -1) {
*sts = errno_Status(errno);
}
}
return TRUE; return TRUE;
}
#endif
return 0;
} }
pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp) pwr_tStatus qos_SignalQue(pwr_tStatus* status, qdb_sQue* qp)
{ {
pwr_dStatus(sts, status, QCOM__SUCCESS); pwr_dStatus(sts, status, QCOM__SUCCESS);
#if !defined(OS_MACOS) && !defined(OS_FREEBSD) && !defined(OS_OPENBSD)
qdb_AssumeLocked; qdb_AssumeLocked;
pthread_mutex_lock(&qp->lock.mutex); pthread_mutex_lock(&qp->lock.mutex);
#endif
qp->lock.waiting = FALSE; qp->lock.waiting = FALSE;
#if !defined(OS_MACOS) && !defined(OS_FREEBSD) && !defined(OS_OPENBSD)
pthread_cond_signal(&qp->lock.cond); pthread_cond_signal(&qp->lock.cond);
pthread_mutex_unlock(&qp->lock.mutex); pthread_mutex_unlock(&qp->lock.mutex);
#endif
return TRUE; return TRUE;
} }
......
...@@ -4,17 +4,17 @@ ...@@ -4,17 +4,17 @@
* *
* This file is part of ProviewR. * This file is part of ProviewR.
* *
* Distribution terms * This program is free software; you can redistribute it and/or
* Permission is hereby granted, free of charge, to any person * modify it under the terms of the GNU General Public License as
* obtaining a copy of this software and associated documentation * published by the Free Software Foundation, either version 2 of
* files (the Software), to deal in the Software without * the License, or (at your option) any later version.
* restriction, including without limitation the rights to use, *
* copy, modify, merge, publish, distribute, sublicense, and/or * This program is distributed in the hope that it will be useful
* sell copies of the Software, and to permit persons to whom * but WITHOUT ANY WARRANTY; without even the implied warranty of
* the Software is furnished to do so, subject to the following * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* conditions: * GNU General Public License for more details.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/> * along with ProviewR. If not, see <http://www.gnu.org/licenses/>
* *
* Linking ProviewR statically or dynamically with other modules is * Linking ProviewR statically or dynamically with other modules is
...@@ -32,12 +32,6 @@ ...@@ -32,12 +32,6 @@
* the source code of ProviewR (the version used to produce the * the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU * combined work), being distributed under the terms of the GNU
* General Public License plus this exception. * General Public License plus this exception.
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHOR OF THIS SOFTWARE BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/ */
/*-< SEMAPHORE.C >--------------------------------------------------*--------*/ /*-< SEMAPHORE.C >--------------------------------------------------*--------*/
...@@ -61,11 +55,13 @@ ...@@ -61,11 +55,13 @@
#include "rt_semaphore.h" #include "rt_semaphore.h"
#if !defined(OS_MACOS) && !defined(OS_FREEBSD) && !defined(OS_OPENBSD)
union semun { union semun {
int val; int val;
struct semid_ds* buf; struct semid_ds* buf;
u_short* array; u_short* array;
}; };
#endif
sem_t* posix_sem_open(const char* name, int oflag, ...) sem_t* posix_sem_open(const char* name, int oflag, ...)
{ {
...@@ -90,7 +86,11 @@ sem_t* posix_sem_open(const char* name, int oflag, ...) ...@@ -90,7 +86,11 @@ sem_t* posix_sem_open(const char* name, int oflag, ...)
int init_value; int init_value;
va_list ap; va_list ap;
va_start(ap, oflag); va_start(ap, oflag);
#if defined(OS_MACOS) || defined(OS_FREEBSD) || defined (OS_OPENBSD)
mode = va_arg(ap, int);
#else
mode = va_arg(ap, mode_t); mode = va_arg(ap, mode_t);
#endif
init_value = va_arg(ap, unsigned int); init_value = va_arg(ap, unsigned int);
if (init_value < 0) { if (init_value < 0) {
errno = EINVAL; errno = EINVAL;
......
...@@ -34,8 +34,6 @@ ...@@ -34,8 +34,6 @@
* General Public License plus this exception. * General Public License plus this exception.
*/ */
/* rt_sect.h */
/*-< SEMAPHORE.H >--------------------------------------------------*--------*/ /*-< SEMAPHORE.H >--------------------------------------------------*--------*/
/* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */ /* POSIX.1b Version 1.0 (c) 1998 GARRET * ? */
/* (POSIX.1b implementation for Linux) * /\| */ /* (POSIX.1b implementation for Linux) * /\| */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment